aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ipl.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r--arch/s390/kernel/ipl.c948
1 files changed, 611 insertions, 337 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index b97694fa62ec..db28cca81fef 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2,7 +2,7 @@
2 * arch/s390/kernel/ipl.c 2 * arch/s390/kernel/ipl.c
3 * ipl/reipl/dump support for Linux on s390. 3 * ipl/reipl/dump support for Linux on s390.
4 * 4 *
5 * Copyright (C) IBM Corp. 2005,2006 5 * Copyright IBM Corp. 2005,2007
6 * Author(s): Michael Holzheu <holzheu@de.ibm.com> 6 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
7 * Heiko Carstens <heiko.carstens@de.ibm.com> 7 * Heiko Carstens <heiko.carstens@de.ibm.com>
8 * Volker Sameske <sameske@de.ibm.com> 8 * Volker Sameske <sameske@de.ibm.com>
@@ -31,6 +31,43 @@
31#define IPL_FCP_DUMP_STR "fcp_dump" 31#define IPL_FCP_DUMP_STR "fcp_dump"
32#define IPL_NSS_STR "nss" 32#define IPL_NSS_STR "nss"
33 33
34#define DUMP_CCW_STR "ccw"
35#define DUMP_FCP_STR "fcp"
36#define DUMP_NONE_STR "none"
37
38/*
39 * Four shutdown trigger types are supported:
40 * - panic
41 * - halt
42 * - power off
43 * - reipl
44 */
45#define ON_PANIC_STR "on_panic"
46#define ON_HALT_STR "on_halt"
47#define ON_POFF_STR "on_poff"
48#define ON_REIPL_STR "on_reboot"
49
50struct shutdown_action;
51struct shutdown_trigger {
52 char *name;
53 struct shutdown_action *action;
54};
55
56/*
57 * Five shutdown action types are supported:
58 */
59#define SHUTDOWN_ACTION_IPL_STR "ipl"
60#define SHUTDOWN_ACTION_REIPL_STR "reipl"
61#define SHUTDOWN_ACTION_DUMP_STR "dump"
62#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd"
63#define SHUTDOWN_ACTION_STOP_STR "stop"
64
65struct shutdown_action {
66 char *name;
67 void (*fn) (struct shutdown_trigger *trigger);
68 int (*init) (void);
69};
70
34static char *ipl_type_str(enum ipl_type type) 71static char *ipl_type_str(enum ipl_type type)
35{ 72{
36 switch (type) { 73 switch (type) {
@@ -54,10 +91,6 @@ enum dump_type {
54 DUMP_TYPE_FCP = 4, 91 DUMP_TYPE_FCP = 4,
55}; 92};
56 93
57#define DUMP_NONE_STR "none"
58#define DUMP_CCW_STR "ccw"
59#define DUMP_FCP_STR "fcp"
60
61static char *dump_type_str(enum dump_type type) 94static char *dump_type_str(enum dump_type type)
62{ 95{
63 switch (type) { 96 switch (type) {
@@ -99,30 +132,6 @@ enum dump_method {
99 DUMP_METHOD_FCP_DIAG, 132 DUMP_METHOD_FCP_DIAG,
100}; 133};
101 134
102enum shutdown_action {
103 SHUTDOWN_REIPL,
104 SHUTDOWN_DUMP,
105 SHUTDOWN_STOP,
106};
107
108#define SHUTDOWN_REIPL_STR "reipl"
109#define SHUTDOWN_DUMP_STR "dump"
110#define SHUTDOWN_STOP_STR "stop"
111
112static char *shutdown_action_str(enum shutdown_action action)
113{
114 switch (action) {
115 case SHUTDOWN_REIPL:
116 return SHUTDOWN_REIPL_STR;
117 case SHUTDOWN_DUMP:
118 return SHUTDOWN_DUMP_STR;
119 case SHUTDOWN_STOP:
120 return SHUTDOWN_STOP_STR;
121 default:
122 return NULL;
123 }
124}
125
126static int diag308_set_works = 0; 135static int diag308_set_works = 0;
127 136
128static int reipl_capabilities = IPL_TYPE_UNKNOWN; 137static int reipl_capabilities = IPL_TYPE_UNKNOWN;
@@ -140,8 +149,6 @@ static enum dump_method dump_method = DUMP_METHOD_NONE;
140static struct ipl_parameter_block *dump_block_fcp; 149static struct ipl_parameter_block *dump_block_fcp;
141static struct ipl_parameter_block *dump_block_ccw; 150static struct ipl_parameter_block *dump_block_ccw;
142 151
143static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
144
145static struct sclp_ipl_info sclp_ipl_info; 152static struct sclp_ipl_info sclp_ipl_info;
146 153
147int diag308(unsigned long subcode, void *addr) 154int diag308(unsigned long subcode, void *addr)
@@ -205,8 +212,8 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
205 struct kobj_attribute *attr, \ 212 struct kobj_attribute *attr, \
206 const char *buf, size_t len) \ 213 const char *buf, size_t len) \
207{ \ 214{ \
208 if (sscanf(buf, _fmt_in, _value) != 1) \ 215 strncpy(_value, buf, sizeof(_value) - 1); \
209 return -EINVAL; \ 216 strstrip(_value); \
210 return len; \ 217 return len; \
211} \ 218} \
212static struct kobj_attribute sys_##_prefix##_##_name##_attr = \ 219static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
@@ -245,33 +252,6 @@ static __init enum ipl_type get_ipl_type(void)
245 return IPL_TYPE_FCP; 252 return IPL_TYPE_FCP;
246} 253}
247 254
248void __init setup_ipl_info(void)
249{
250 ipl_info.type = get_ipl_type();
251 switch (ipl_info.type) {
252 case IPL_TYPE_CCW:
253 ipl_info.data.ccw.dev_id.devno = ipl_devno;
254 ipl_info.data.ccw.dev_id.ssid = 0;
255 break;
256 case IPL_TYPE_FCP:
257 case IPL_TYPE_FCP_DUMP:
258 ipl_info.data.fcp.dev_id.devno =
259 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
260 ipl_info.data.fcp.dev_id.ssid = 0;
261 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
262 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
263 break;
264 case IPL_TYPE_NSS:
265 strncpy(ipl_info.data.nss.name, kernel_nss_name,
266 sizeof(ipl_info.data.nss.name));
267 break;
268 case IPL_TYPE_UNKNOWN:
269 default:
270 /* We have no info to copy */
271 break;
272 }
273}
274
275struct ipl_info ipl_info; 255struct ipl_info ipl_info;
276EXPORT_SYMBOL_GPL(ipl_info); 256EXPORT_SYMBOL_GPL(ipl_info);
277 257
@@ -428,8 +408,74 @@ static struct attribute_group ipl_unknown_attr_group = {
428 408
429static struct kset *ipl_kset; 409static struct kset *ipl_kset;
430 410
411static int __init ipl_register_fcp_files(void)
412{
413 int rc;
414
415 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
416 if (rc)
417 goto out;
418 rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
419 if (rc)
420 goto out_ipl_parm;
421 rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_scp_data_attr);
422 if (!rc)
423 goto out;
424
425 sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
426
427out_ipl_parm:
428 sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
429out:
430 return rc;
431}
432
433static void ipl_run(struct shutdown_trigger *trigger)
434{
435 diag308(DIAG308_IPL, NULL);
436 if (MACHINE_IS_VM)
437 __cpcmd("IPL", NULL, 0, NULL);
438 else if (ipl_info.type == IPL_TYPE_CCW)
439 reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
440}
441
442static int ipl_init(void)
443{
444 int rc;
445
446 ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
447 if (!ipl_kset) {
448 rc = -ENOMEM;
449 goto out;
450 }
451 switch (ipl_info.type) {
452 case IPL_TYPE_CCW:
453 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group);
454 break;
455 case IPL_TYPE_FCP:
456 case IPL_TYPE_FCP_DUMP:
457 rc = ipl_register_fcp_files();
458 break;
459 case IPL_TYPE_NSS:
460 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group);
461 break;
462 default:
463 rc = sysfs_create_group(&ipl_kset->kobj,
464 &ipl_unknown_attr_group);
465 break;
466 }
467out:
468 if (rc)
469 panic("ipl_init failed: rc = %i\n", rc);
470
471 return 0;
472}
473
474static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
475 ipl_init};
476
431/* 477/*
432 * reipl section 478 * reipl shutdown action: Reboot Linux on shutdown.
433 */ 479 */
434 480
435/* FCP reipl device attributes */ 481/* FCP reipl device attributes */
@@ -549,7 +595,9 @@ static int reipl_set_type(enum ipl_type type)
549 595
550 switch(type) { 596 switch(type) {
551 case IPL_TYPE_CCW: 597 case IPL_TYPE_CCW:
552 if (MACHINE_IS_VM) 598 if (diag308_set_works)
599 reipl_method = REIPL_METHOD_CCW_DIAG;
600 else if (MACHINE_IS_VM)
553 reipl_method = REIPL_METHOD_CCW_VM; 601 reipl_method = REIPL_METHOD_CCW_VM;
554 else 602 else
555 reipl_method = REIPL_METHOD_CCW_CIO; 603 reipl_method = REIPL_METHOD_CCW_CIO;
@@ -600,143 +648,11 @@ static ssize_t reipl_type_store(struct kobject *kobj,
600} 648}
601 649
602static struct kobj_attribute reipl_type_attr = 650static struct kobj_attribute reipl_type_attr =
603 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store); 651 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
604 652
605static struct kset *reipl_kset; 653static struct kset *reipl_kset;
606 654
607/* 655void reipl_run(struct shutdown_trigger *trigger)
608 * dump section
609 */
610
611/* FCP dump device attributes */
612
613DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
614 dump_block_fcp->ipl_info.fcp.wwpn);
615DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
616 dump_block_fcp->ipl_info.fcp.lun);
617DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
618 dump_block_fcp->ipl_info.fcp.bootprog);
619DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
620 dump_block_fcp->ipl_info.fcp.br_lba);
621DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
622 dump_block_fcp->ipl_info.fcp.devno);
623
624static struct attribute *dump_fcp_attrs[] = {
625 &sys_dump_fcp_device_attr.attr,
626 &sys_dump_fcp_wwpn_attr.attr,
627 &sys_dump_fcp_lun_attr.attr,
628 &sys_dump_fcp_bootprog_attr.attr,
629 &sys_dump_fcp_br_lba_attr.attr,
630 NULL,
631};
632
633static struct attribute_group dump_fcp_attr_group = {
634 .name = IPL_FCP_STR,
635 .attrs = dump_fcp_attrs,
636};
637
638/* CCW dump device attributes */
639
640DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
641 dump_block_ccw->ipl_info.ccw.devno);
642
643static struct attribute *dump_ccw_attrs[] = {
644 &sys_dump_ccw_device_attr.attr,
645 NULL,
646};
647
648static struct attribute_group dump_ccw_attr_group = {
649 .name = IPL_CCW_STR,
650 .attrs = dump_ccw_attrs,
651};
652
653/* dump type */
654
655static int dump_set_type(enum dump_type type)
656{
657 if (!(dump_capabilities & type))
658 return -EINVAL;
659 switch(type) {
660 case DUMP_TYPE_CCW:
661 if (MACHINE_IS_VM)
662 dump_method = DUMP_METHOD_CCW_VM;
663 else if (diag308_set_works)
664 dump_method = DUMP_METHOD_CCW_DIAG;
665 else
666 dump_method = DUMP_METHOD_CCW_CIO;
667 break;
668 case DUMP_TYPE_FCP:
669 dump_method = DUMP_METHOD_FCP_DIAG;
670 break;
671 default:
672 dump_method = DUMP_METHOD_NONE;
673 }
674 dump_type = type;
675 return 0;
676}
677
678static ssize_t dump_type_show(struct kobject *kobj,
679 struct kobj_attribute *attr, char *page)
680{
681 return sprintf(page, "%s\n", dump_type_str(dump_type));
682}
683
684static ssize_t dump_type_store(struct kobject *kobj,
685 struct kobj_attribute *attr,
686 const char *buf, size_t len)
687{
688 int rc = -EINVAL;
689
690 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
691 rc = dump_set_type(DUMP_TYPE_NONE);
692 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
693 rc = dump_set_type(DUMP_TYPE_CCW);
694 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
695 rc = dump_set_type(DUMP_TYPE_FCP);
696 return (rc != 0) ? rc : len;
697}
698
699static struct kobj_attribute dump_type_attr =
700 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
701
702static struct kset *dump_kset;
703
704/*
705 * Shutdown actions section
706 */
707
708static struct kset *shutdown_actions_kset;
709
710/* on panic */
711
712static ssize_t on_panic_show(struct kobject *kobj,
713 struct kobj_attribute *attr, char *page)
714{
715 return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
716}
717
718static ssize_t on_panic_store(struct kobject *kobj,
719 struct kobj_attribute *attr,
720 const char *buf, size_t len)
721{
722 if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
723 on_panic_action = SHUTDOWN_REIPL;
724 else if (strncmp(buf, SHUTDOWN_DUMP_STR,
725 strlen(SHUTDOWN_DUMP_STR)) == 0)
726 on_panic_action = SHUTDOWN_DUMP;
727 else if (strncmp(buf, SHUTDOWN_STOP_STR,
728 strlen(SHUTDOWN_STOP_STR)) == 0)
729 on_panic_action = SHUTDOWN_STOP;
730 else
731 return -EINVAL;
732
733 return len;
734}
735
736static struct kobj_attribute on_panic_attr =
737 __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
738
739void do_reipl(void)
740{ 656{
741 struct ccw_dev_id devid; 657 struct ccw_dev_id devid;
742 static char buf[100]; 658 static char buf[100];
@@ -745,8 +661,6 @@ void do_reipl(void)
745 switch (reipl_method) { 661 switch (reipl_method) {
746 case REIPL_METHOD_CCW_CIO: 662 case REIPL_METHOD_CCW_CIO:
747 devid.devno = reipl_block_ccw->ipl_info.ccw.devno; 663 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
748 if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
749 diag308(DIAG308_IPL, NULL);
750 devid.ssid = 0; 664 devid.ssid = 0;
751 reipl_ccw_dev(&devid); 665 reipl_ccw_dev(&devid);
752 break; 666 break;
@@ -787,98 +701,6 @@ void do_reipl(void)
787 default: 701 default:
788 break; 702 break;
789 } 703 }
790 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
791}
792
793static void do_dump(void)
794{
795 struct ccw_dev_id devid;
796 static char buf[100];
797
798 switch (dump_method) {
799 case DUMP_METHOD_CCW_CIO:
800 smp_send_stop();
801 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
802 devid.ssid = 0;
803 reipl_ccw_dev(&devid);
804 break;
805 case DUMP_METHOD_CCW_VM:
806 smp_send_stop();
807 sprintf(buf, "STORE STATUS");
808 __cpcmd(buf, NULL, 0, NULL);
809 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
810 __cpcmd(buf, NULL, 0, NULL);
811 break;
812 case DUMP_METHOD_CCW_DIAG:
813 diag308(DIAG308_SET, dump_block_ccw);
814 diag308(DIAG308_DUMP, NULL);
815 break;
816 case DUMP_METHOD_FCP_DIAG:
817 diag308(DIAG308_SET, dump_block_fcp);
818 diag308(DIAG308_DUMP, NULL);
819 break;
820 case DUMP_METHOD_NONE:
821 default:
822 return;
823 }
824 printk(KERN_EMERG "Dump failed!\n");
825}
826
827/* init functions */
828
829static int __init ipl_register_fcp_files(void)
830{
831 int rc;
832
833 rc = sysfs_create_group(&ipl_kset->kobj,
834 &ipl_fcp_attr_group);
835 if (rc)
836 goto out;
837 rc = sysfs_create_bin_file(&ipl_kset->kobj,
838 &ipl_parameter_attr);
839 if (rc)
840 goto out_ipl_parm;
841 rc = sysfs_create_bin_file(&ipl_kset->kobj,
842 &ipl_scp_data_attr);
843 if (!rc)
844 goto out;
845
846 sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
847
848out_ipl_parm:
849 sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
850out:
851 return rc;
852}
853
854static int __init ipl_init(void)
855{
856 int rc;
857
858 ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj);
859 if (!ipl_kset)
860 return -ENOMEM;
861 switch (ipl_info.type) {
862 case IPL_TYPE_CCW:
863 rc = sysfs_create_group(&ipl_kset->kobj,
864 &ipl_ccw_attr_group);
865 break;
866 case IPL_TYPE_FCP:
867 case IPL_TYPE_FCP_DUMP:
868 rc = ipl_register_fcp_files();
869 break;
870 case IPL_TYPE_NSS:
871 rc = sysfs_create_group(&ipl_kset->kobj,
872 &ipl_nss_attr_group);
873 break;
874 default:
875 rc = sysfs_create_group(&ipl_kset->kobj,
876 &ipl_unknown_attr_group);
877 break;
878 }
879 if (rc)
880 kset_unregister(ipl_kset);
881 return rc;
882} 704}
883 705
884static void __init reipl_probe(void) 706static void __init reipl_probe(void)
@@ -923,6 +745,7 @@ static int __init reipl_ccw_init(void)
923 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; 745 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
924 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; 746 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
925 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; 747 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
748 reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID;
926 /* check if read scp info worked and set loadparm */ 749 /* check if read scp info worked and set loadparm */
927 if (sclp_ipl_info.is_valid) 750 if (sclp_ipl_info.is_valid)
928 memcpy(reipl_block_ccw->ipl_info.ccw.load_param, 751 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
@@ -931,8 +754,7 @@ static int __init reipl_ccw_init(void)
931 /* read scp info failed: set empty loadparm (EBCDIC blanks) */ 754 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
932 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, 755 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
933 LOADPARM_LEN); 756 LOADPARM_LEN);
934 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */ 757 if (!MACHINE_IS_VM && !diag308_set_works)
935 if (!MACHINE_IS_VM)
936 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; 758 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
937 if (ipl_info.type == IPL_TYPE_CCW) 759 if (ipl_info.type == IPL_TYPE_CCW)
938 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; 760 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
@@ -970,7 +792,7 @@ static int __init reipl_fcp_init(void)
970 return 0; 792 return 0;
971} 793}
972 794
973static int __init reipl_init(void) 795static int reipl_init(void)
974{ 796{
975 int rc; 797 int rc;
976 798
@@ -997,6 +819,140 @@ static int __init reipl_init(void)
997 return 0; 819 return 0;
998} 820}
999 821
822static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
823 reipl_run, reipl_init};
824
825/*
826 * dump shutdown action: Dump Linux on shutdown.
827 */
828
829/* FCP dump device attributes */
830
831DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
832 dump_block_fcp->ipl_info.fcp.wwpn);
833DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
834 dump_block_fcp->ipl_info.fcp.lun);
835DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
836 dump_block_fcp->ipl_info.fcp.bootprog);
837DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
838 dump_block_fcp->ipl_info.fcp.br_lba);
839DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
840 dump_block_fcp->ipl_info.fcp.devno);
841
842static struct attribute *dump_fcp_attrs[] = {
843 &sys_dump_fcp_device_attr.attr,
844 &sys_dump_fcp_wwpn_attr.attr,
845 &sys_dump_fcp_lun_attr.attr,
846 &sys_dump_fcp_bootprog_attr.attr,
847 &sys_dump_fcp_br_lba_attr.attr,
848 NULL,
849};
850
851static struct attribute_group dump_fcp_attr_group = {
852 .name = IPL_FCP_STR,
853 .attrs = dump_fcp_attrs,
854};
855
856/* CCW dump device attributes */
857
858DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
859 dump_block_ccw->ipl_info.ccw.devno);
860
861static struct attribute *dump_ccw_attrs[] = {
862 &sys_dump_ccw_device_attr.attr,
863 NULL,
864};
865
866static struct attribute_group dump_ccw_attr_group = {
867 .name = IPL_CCW_STR,
868 .attrs = dump_ccw_attrs,
869};
870
871/* dump type */
872
873static int dump_set_type(enum dump_type type)
874{
875 if (!(dump_capabilities & type))
876 return -EINVAL;
877 switch (type) {
878 case DUMP_TYPE_CCW:
879 if (diag308_set_works)
880 dump_method = DUMP_METHOD_CCW_DIAG;
881 else if (MACHINE_IS_VM)
882 dump_method = DUMP_METHOD_CCW_VM;
883 else
884 dump_method = DUMP_METHOD_CCW_CIO;
885 break;
886 case DUMP_TYPE_FCP:
887 dump_method = DUMP_METHOD_FCP_DIAG;
888 break;
889 default:
890 dump_method = DUMP_METHOD_NONE;
891 }
892 dump_type = type;
893 return 0;
894}
895
896static ssize_t dump_type_show(struct kobject *kobj,
897 struct kobj_attribute *attr, char *page)
898{
899 return sprintf(page, "%s\n", dump_type_str(dump_type));
900}
901
902static ssize_t dump_type_store(struct kobject *kobj,
903 struct kobj_attribute *attr,
904 const char *buf, size_t len)
905{
906 int rc = -EINVAL;
907
908 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
909 rc = dump_set_type(DUMP_TYPE_NONE);
910 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
911 rc = dump_set_type(DUMP_TYPE_CCW);
912 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
913 rc = dump_set_type(DUMP_TYPE_FCP);
914 return (rc != 0) ? rc : len;
915}
916
917static struct kobj_attribute dump_type_attr =
918 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
919
920static struct kset *dump_kset;
921
922static void dump_run(struct shutdown_trigger *trigger)
923{
924 struct ccw_dev_id devid;
925 static char buf[100];
926
927 switch (dump_method) {
928 case DUMP_METHOD_CCW_CIO:
929 smp_send_stop();
930 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
931 devid.ssid = 0;
932 reipl_ccw_dev(&devid);
933 break;
934 case DUMP_METHOD_CCW_VM:
935 smp_send_stop();
936 sprintf(buf, "STORE STATUS");
937 __cpcmd(buf, NULL, 0, NULL);
938 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
939 __cpcmd(buf, NULL, 0, NULL);
940 break;
941 case DUMP_METHOD_CCW_DIAG:
942 diag308(DIAG308_SET, dump_block_ccw);
943 diag308(DIAG308_DUMP, NULL);
944 break;
945 case DUMP_METHOD_FCP_DIAG:
946 diag308(DIAG308_SET, dump_block_fcp);
947 diag308(DIAG308_DUMP, NULL);
948 break;
949 case DUMP_METHOD_NONE:
950 default:
951 return;
952 }
953 printk(KERN_EMERG "Dump failed!\n");
954}
955
1000static int __init dump_ccw_init(void) 956static int __init dump_ccw_init(void)
1001{ 957{
1002 int rc; 958 int rc;
@@ -1042,31 +998,14 @@ static int __init dump_fcp_init(void)
1042 return 0; 998 return 0;
1043} 999}
1044 1000
1045#define SHUTDOWN_ON_PANIC_PRIO 0 1001static int dump_init(void)
1046
1047static int shutdown_on_panic_notify(struct notifier_block *self,
1048 unsigned long event, void *data)
1049{
1050 if (on_panic_action == SHUTDOWN_DUMP)
1051 do_dump();
1052 else if (on_panic_action == SHUTDOWN_REIPL)
1053 do_reipl();
1054 return NOTIFY_OK;
1055}
1056
1057static struct notifier_block shutdown_on_panic_nb = {
1058 .notifier_call = shutdown_on_panic_notify,
1059 .priority = SHUTDOWN_ON_PANIC_PRIO
1060};
1061
1062static int __init dump_init(void)
1063{ 1002{
1064 int rc; 1003 int rc;
1065 1004
1066 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj); 1005 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
1067 if (!dump_kset) 1006 if (!dump_kset)
1068 return -ENOMEM; 1007 return -ENOMEM;
1069 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr); 1008 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
1070 if (rc) { 1009 if (rc) {
1071 kset_unregister(dump_kset); 1010 kset_unregister(dump_kset);
1072 return rc; 1011 return rc;
@@ -1081,47 +1020,381 @@ static int __init dump_init(void)
1081 return 0; 1020 return 0;
1082} 1021}
1083 1022
1084static int __init shutdown_actions_init(void) 1023static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
1024 dump_run, dump_init};
1025
1026/*
1027 * vmcmd shutdown action: Trigger vm command on shutdown.
1028 */
1029
1030static char vmcmd_on_reboot[128];
1031static char vmcmd_on_panic[128];
1032static char vmcmd_on_halt[128];
1033static char vmcmd_on_poff[128];
1034
1035DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
1036DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
1037DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
1038DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
1039
1040static struct attribute *vmcmd_attrs[] = {
1041 &sys_vmcmd_on_reboot_attr.attr,
1042 &sys_vmcmd_on_panic_attr.attr,
1043 &sys_vmcmd_on_halt_attr.attr,
1044 &sys_vmcmd_on_poff_attr.attr,
1045 NULL,
1046};
1047
1048static struct attribute_group vmcmd_attr_group = {
1049 .attrs = vmcmd_attrs,
1050};
1051
1052static struct kset *vmcmd_kset;
1053
1054static void vmcmd_run(struct shutdown_trigger *trigger)
1055{
1056 char *cmd, *next_cmd;
1057
1058 if (strcmp(trigger->name, ON_REIPL_STR) == 0)
1059 cmd = vmcmd_on_reboot;
1060 else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1061 cmd = vmcmd_on_panic;
1062 else if (strcmp(trigger->name, ON_HALT_STR) == 0)
1063 cmd = vmcmd_on_halt;
1064 else if (strcmp(trigger->name, ON_POFF_STR) == 0)
1065 cmd = vmcmd_on_poff;
1066 else
1067 return;
1068
1069 if (strlen(cmd) == 0)
1070 return;
1071 do {
1072 next_cmd = strchr(cmd, '\n');
1073 if (next_cmd) {
1074 next_cmd[0] = 0;
1075 next_cmd += 1;
1076 }
1077 __cpcmd(cmd, NULL, 0, NULL);
1078 cmd = next_cmd;
1079 } while (cmd != NULL);
1080}
1081
1082static int vmcmd_init(void)
1085{ 1083{
1086 int rc; 1084 if (!MACHINE_IS_VM)
1085 return -ENOTSUPP;
1086 vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
1087 if (!vmcmd_kset)
1088 return -ENOMEM;
1089 return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
1090}
1091
1092static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
1093 vmcmd_run, vmcmd_init};
1094
1095/*
1096 * stop shutdown action: Stop Linux on shutdown.
1097 */
1098
1099static void stop_run(struct shutdown_trigger *trigger)
1100{
1101 if (strcmp(trigger->name, ON_PANIC_STR) == 0)
1102 disabled_wait((unsigned long) __builtin_return_address(0));
1103 else {
1104 signal_processor(smp_processor_id(), sigp_stop);
1105 for (;;);
1106 }
1107}
1108
1109static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
1110 stop_run, NULL};
1111
1112/* action list */
1113
1114static struct shutdown_action *shutdown_actions_list[] = {
1115 &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action};
1116#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
1117
1118/*
1119 * Trigger section
1120 */
1121
1122static struct kset *shutdown_actions_kset;
1123
1124static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
1125 size_t len)
1126{
1127 int i;
1128 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1129 if (!shutdown_actions_list[i])
1130 continue;
1131 if (strncmp(buf, shutdown_actions_list[i]->name,
1132 strlen(shutdown_actions_list[i]->name)) == 0) {
1133 trigger->action = shutdown_actions_list[i];
1134 return len;
1135 }
1136 }
1137 return -EINVAL;
1138}
1139
1140/* on reipl */
1141
1142static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
1143 &reipl_action};
1144
1145static ssize_t on_reboot_show(struct kobject *kobj,
1146 struct kobj_attribute *attr, char *page)
1147{
1148 return sprintf(page, "%s\n", on_reboot_trigger.action->name);
1149}
1150
1151static ssize_t on_reboot_store(struct kobject *kobj,
1152 struct kobj_attribute *attr,
1153 const char *buf, size_t len)
1154{
1155 return set_trigger(buf, &on_reboot_trigger, len);
1156}
1157
1158static struct kobj_attribute on_reboot_attr =
1159 __ATTR(on_reboot, 0644, on_reboot_show, on_reboot_store);
1160
1161static void do_machine_restart(char *__unused)
1162{
1163 smp_send_stop();
1164 on_reboot_trigger.action->fn(&on_reboot_trigger);
1165 reipl_run(NULL);
1166}
1167void (*_machine_restart)(char *command) = do_machine_restart;
1168
1169/* on panic */
1170
1171static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
1172
1173static ssize_t on_panic_show(struct kobject *kobj,
1174 struct kobj_attribute *attr, char *page)
1175{
1176 return sprintf(page, "%s\n", on_panic_trigger.action->name);
1177}
1087 1178
1179static ssize_t on_panic_store(struct kobject *kobj,
1180 struct kobj_attribute *attr,
1181 const char *buf, size_t len)
1182{
1183 return set_trigger(buf, &on_panic_trigger, len);
1184}
1185
1186static struct kobj_attribute on_panic_attr =
1187 __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
1188
1189static void do_panic(void)
1190{
1191 on_panic_trigger.action->fn(&on_panic_trigger);
1192 stop_run(&on_panic_trigger);
1193}
1194
1195/* on halt */
1196
1197static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
1198
1199static ssize_t on_halt_show(struct kobject *kobj,
1200 struct kobj_attribute *attr, char *page)
1201{
1202 return sprintf(page, "%s\n", on_halt_trigger.action->name);
1203}
1204
1205static ssize_t on_halt_store(struct kobject *kobj,
1206 struct kobj_attribute *attr,
1207 const char *buf, size_t len)
1208{
1209 return set_trigger(buf, &on_halt_trigger, len);
1210}
1211
1212static struct kobj_attribute on_halt_attr =
1213 __ATTR(on_halt, 0644, on_halt_show, on_halt_store);
1214
1215
1216static void do_machine_halt(void)
1217{
1218 smp_send_stop();
1219 on_halt_trigger.action->fn(&on_halt_trigger);
1220 stop_run(&on_halt_trigger);
1221}
1222void (*_machine_halt)(void) = do_machine_halt;
1223
1224/* on power off */
1225
1226static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
1227
1228static ssize_t on_poff_show(struct kobject *kobj,
1229 struct kobj_attribute *attr, char *page)
1230{
1231 return sprintf(page, "%s\n", on_poff_trigger.action->name);
1232}
1233
1234static ssize_t on_poff_store(struct kobject *kobj,
1235 struct kobj_attribute *attr,
1236 const char *buf, size_t len)
1237{
1238 return set_trigger(buf, &on_poff_trigger, len);
1239}
1240
1241static struct kobj_attribute on_poff_attr =
1242 __ATTR(on_poff, 0644, on_poff_show, on_poff_store);
1243
1244
1245static void do_machine_power_off(void)
1246{
1247 smp_send_stop();
1248 on_poff_trigger.action->fn(&on_poff_trigger);
1249 stop_run(&on_poff_trigger);
1250}
1251void (*_machine_power_off)(void) = do_machine_power_off;
1252
1253static void __init shutdown_triggers_init(void)
1254{
1088 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL, 1255 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
1089 firmware_kobj); 1256 firmware_kobj);
1090 if (!shutdown_actions_kset) 1257 if (!shutdown_actions_kset)
1091 return -ENOMEM; 1258 goto fail;
1092 rc = sysfs_create_file(&shutdown_actions_kset->kobj, &on_panic_attr); 1259 if (sysfs_create_file(&shutdown_actions_kset->kobj,
1093 if (rc) { 1260 &on_reboot_attr.attr))
1094 kset_unregister(shutdown_actions_kset); 1261 goto fail;
1095 return rc; 1262 if (sysfs_create_file(&shutdown_actions_kset->kobj,
1263 &on_panic_attr.attr))
1264 goto fail;
1265 if (sysfs_create_file(&shutdown_actions_kset->kobj,
1266 &on_halt_attr.attr))
1267 goto fail;
1268 if (sysfs_create_file(&shutdown_actions_kset->kobj,
1269 &on_poff_attr.attr))
1270 goto fail;
1271
1272 return;
1273fail:
1274 panic("shutdown_triggers_init failed\n");
1275}
1276
1277static void __init shutdown_actions_init(void)
1278{
1279 int i;
1280
1281 for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
1282 if (!shutdown_actions_list[i]->init)
1283 continue;
1284 if (shutdown_actions_list[i]->init())
1285 shutdown_actions_list[i] = NULL;
1096 } 1286 }
1097 atomic_notifier_chain_register(&panic_notifier_list,
1098 &shutdown_on_panic_nb);
1099 return 0;
1100} 1287}
1101 1288
1102static int __init s390_ipl_init(void) 1289static int __init s390_ipl_init(void)
1103{ 1290{
1104 int rc;
1105
1106 sclp_get_ipl_info(&sclp_ipl_info);
1107 reipl_probe(); 1291 reipl_probe();
1108 rc = ipl_init(); 1292 sclp_get_ipl_info(&sclp_ipl_info);
1109 if (rc) 1293 shutdown_actions_init();
1110 return rc; 1294 shutdown_triggers_init();
1111 rc = reipl_init();
1112 if (rc)
1113 return rc;
1114 rc = dump_init();
1115 if (rc)
1116 return rc;
1117 rc = shutdown_actions_init();
1118 if (rc)
1119 return rc;
1120 return 0; 1295 return 0;
1121} 1296}
1122 1297
1123__initcall(s390_ipl_init); 1298__initcall(s390_ipl_init);
1124 1299
1300static void __init strncpy_skip_quote(char *dst, char *src, int n)
1301{
1302 int sx, dx;
1303
1304 dx = 0;
1305 for (sx = 0; src[sx] != 0; sx++) {
1306 if (src[sx] == '"')
1307 continue;
1308 dst[dx++] = src[sx];
1309 if (dx >= n)
1310 break;
1311 }
1312}
1313
1314static int __init vmcmd_on_reboot_setup(char *str)
1315{
1316 if (!MACHINE_IS_VM)
1317 return 1;
1318 strncpy_skip_quote(vmcmd_on_reboot, str, 127);
1319 vmcmd_on_reboot[127] = 0;
1320 on_reboot_trigger.action = &vmcmd_action;
1321 return 1;
1322}
1323__setup("vmreboot=", vmcmd_on_reboot_setup);
1324
1325static int __init vmcmd_on_panic_setup(char *str)
1326{
1327 if (!MACHINE_IS_VM)
1328 return 1;
1329 strncpy_skip_quote(vmcmd_on_panic, str, 127);
1330 vmcmd_on_panic[127] = 0;
1331 on_panic_trigger.action = &vmcmd_action;
1332 return 1;
1333}
1334__setup("vmpanic=", vmcmd_on_panic_setup);
1335
1336static int __init vmcmd_on_halt_setup(char *str)
1337{
1338 if (!MACHINE_IS_VM)
1339 return 1;
1340 strncpy_skip_quote(vmcmd_on_halt, str, 127);
1341 vmcmd_on_halt[127] = 0;
1342 on_halt_trigger.action = &vmcmd_action;
1343 return 1;
1344}
1345__setup("vmhalt=", vmcmd_on_halt_setup);
1346
1347static int __init vmcmd_on_poff_setup(char *str)
1348{
1349 if (!MACHINE_IS_VM)
1350 return 1;
1351 strncpy_skip_quote(vmcmd_on_poff, str, 127);
1352 vmcmd_on_poff[127] = 0;
1353 on_poff_trigger.action = &vmcmd_action;
1354 return 1;
1355}
1356__setup("vmpoff=", vmcmd_on_poff_setup);
1357
1358static int on_panic_notify(struct notifier_block *self,
1359 unsigned long event, void *data)
1360{
1361 do_panic();
1362 return NOTIFY_OK;
1363}
1364
1365static struct notifier_block on_panic_nb = {
1366 .notifier_call = on_panic_notify,
1367 .priority = 0,
1368};
1369
1370void __init setup_ipl(void)
1371{
1372 ipl_info.type = get_ipl_type();
1373 switch (ipl_info.type) {
1374 case IPL_TYPE_CCW:
1375 ipl_info.data.ccw.dev_id.devno = ipl_devno;
1376 ipl_info.data.ccw.dev_id.ssid = 0;
1377 break;
1378 case IPL_TYPE_FCP:
1379 case IPL_TYPE_FCP_DUMP:
1380 ipl_info.data.fcp.dev_id.devno =
1381 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
1382 ipl_info.data.fcp.dev_id.ssid = 0;
1383 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
1384 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
1385 break;
1386 case IPL_TYPE_NSS:
1387 strncpy(ipl_info.data.nss.name, kernel_nss_name,
1388 sizeof(ipl_info.data.nss.name));
1389 break;
1390 case IPL_TYPE_UNKNOWN:
1391 default:
1392 /* We have no info to copy */
1393 break;
1394 }
1395 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
1396}
1397
1125void __init ipl_save_parameters(void) 1398void __init ipl_save_parameters(void)
1126{ 1399{
1127 struct cio_iplinfo iplinfo; 1400 struct cio_iplinfo iplinfo;
@@ -1202,3 +1475,4 @@ void s390_reset_system(void)
1202 1475
1203 do_reset_calls(); 1476 do_reset_calls();
1204} 1477}
1478