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.c1035
1 files changed, 663 insertions, 372 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index ce0856d32500..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)
@@ -162,22 +169,25 @@ EXPORT_SYMBOL_GPL(diag308);
162/* SYSFS */ 169/* SYSFS */
163 170
164#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \ 171#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
165static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ 172static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
173 struct kobj_attribute *attr, \
166 char *page) \ 174 char *page) \
167{ \ 175{ \
168 return sprintf(page, _format, _value); \ 176 return sprintf(page, _format, _value); \
169} \ 177} \
170static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ 178static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
171 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL); 179 __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
172 180
173#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \ 181#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
174static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ 182static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
183 struct kobj_attribute *attr, \
175 char *page) \ 184 char *page) \
176{ \ 185{ \
177 return sprintf(page, _fmt_out, \ 186 return sprintf(page, _fmt_out, \
178 (unsigned long long) _value); \ 187 (unsigned long long) _value); \
179} \ 188} \
180static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \ 189static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
190 struct kobj_attribute *attr, \
181 const char *buf, size_t len) \ 191 const char *buf, size_t len) \
182{ \ 192{ \
183 unsigned long long value; \ 193 unsigned long long value; \
@@ -186,25 +196,27 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \
186 _value = value; \ 196 _value = value; \
187 return len; \ 197 return len; \
188} \ 198} \
189static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ 199static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
190 __ATTR(_name,(S_IRUGO | S_IWUSR), \ 200 __ATTR(_name,(S_IRUGO | S_IWUSR), \
191 sys_##_prefix##_##_name##_show, \ 201 sys_##_prefix##_##_name##_show, \
192 sys_##_prefix##_##_name##_store); 202 sys_##_prefix##_##_name##_store);
193 203
194#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\ 204#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
195static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ 205static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
206 struct kobj_attribute *attr, \
196 char *page) \ 207 char *page) \
197{ \ 208{ \
198 return sprintf(page, _fmt_out, _value); \ 209 return sprintf(page, _fmt_out, _value); \
199} \ 210} \
200static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \ 211static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
212 struct kobj_attribute *attr, \
201 const char *buf, size_t len) \ 213 const char *buf, size_t len) \
202{ \ 214{ \
203 if (sscanf(buf, _fmt_in, _value) != 1) \ 215 strncpy(_value, buf, sizeof(_value) - 1); \
204 return -EINVAL; \ 216 strstrip(_value); \
205 return len; \ 217 return len; \
206} \ 218} \
207static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ 219static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
208 __ATTR(_name,(S_IRUGO | S_IWUSR), \ 220 __ATTR(_name,(S_IRUGO | S_IWUSR), \
209 sys_##_prefix##_##_name##_show, \ 221 sys_##_prefix##_##_name##_show, \
210 sys_##_prefix##_##_name##_store); 222 sys_##_prefix##_##_name##_store);
@@ -240,44 +252,19 @@ static __init enum ipl_type get_ipl_type(void)
240 return IPL_TYPE_FCP; 252 return IPL_TYPE_FCP;
241} 253}
242 254
243void __init setup_ipl_info(void)
244{
245 ipl_info.type = get_ipl_type();
246 switch (ipl_info.type) {
247 case IPL_TYPE_CCW:
248 ipl_info.data.ccw.dev_id.devno = ipl_devno;
249 ipl_info.data.ccw.dev_id.ssid = 0;
250 break;
251 case IPL_TYPE_FCP:
252 case IPL_TYPE_FCP_DUMP:
253 ipl_info.data.fcp.dev_id.devno =
254 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
255 ipl_info.data.fcp.dev_id.ssid = 0;
256 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
257 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
258 break;
259 case IPL_TYPE_NSS:
260 strncpy(ipl_info.data.nss.name, kernel_nss_name,
261 sizeof(ipl_info.data.nss.name));
262 break;
263 case IPL_TYPE_UNKNOWN:
264 default:
265 /* We have no info to copy */
266 break;
267 }
268}
269
270struct ipl_info ipl_info; 255struct ipl_info ipl_info;
271EXPORT_SYMBOL_GPL(ipl_info); 256EXPORT_SYMBOL_GPL(ipl_info);
272 257
273static ssize_t ipl_type_show(struct kset *kset, char *page) 258static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
259 char *page)
274{ 260{
275 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type)); 261 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
276} 262}
277 263
278static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); 264static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
279 265
280static ssize_t sys_ipl_device_show(struct kset *kset, char *page) 266static ssize_t sys_ipl_device_show(struct kobject *kobj,
267 struct kobj_attribute *attr, char *page)
281{ 268{
282 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 269 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
283 270
@@ -292,7 +279,7 @@ static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
292 } 279 }
293} 280}
294 281
295static struct subsys_attribute sys_ipl_device_attr = 282static struct kobj_attribute sys_ipl_device_attr =
296 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); 283 __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
297 284
298static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr, 285static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
@@ -367,7 +354,8 @@ static struct attribute_group ipl_fcp_attr_group = {
367 354
368/* CCW ipl device attributes */ 355/* CCW ipl device attributes */
369 356
370static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) 357static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
358 struct kobj_attribute *attr, char *page)
371{ 359{
372 char loadparm[LOADPARM_LEN + 1] = {}; 360 char loadparm[LOADPARM_LEN + 1] = {};
373 361
@@ -379,7 +367,7 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
379 return sprintf(page, "%s\n", loadparm); 367 return sprintf(page, "%s\n", loadparm);
380} 368}
381 369
382static struct subsys_attribute sys_ipl_ccw_loadparm_attr = 370static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
383 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); 371 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
384 372
385static struct attribute *ipl_ccw_attrs[] = { 373static struct attribute *ipl_ccw_attrs[] = {
@@ -418,10 +406,76 @@ static struct attribute_group ipl_unknown_attr_group = {
418 .attrs = ipl_unknown_attrs, 406 .attrs = ipl_unknown_attrs,
419}; 407};
420 408
421static decl_subsys(ipl, NULL, NULL); 409static struct kset *ipl_kset;
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};
422 476
423/* 477/*
424 * reipl section 478 * reipl shutdown action: Reboot Linux on shutdown.
425 */ 479 */
426 480
427/* FCP reipl device attributes */ 481/* FCP reipl device attributes */
@@ -465,7 +519,8 @@ static void reipl_get_ascii_loadparm(char *loadparm)
465 strstrip(loadparm); 519 strstrip(loadparm);
466} 520}
467 521
468static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page) 522static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
523 struct kobj_attribute *attr, char *page)
469{ 524{
470 char buf[LOADPARM_LEN + 1]; 525 char buf[LOADPARM_LEN + 1];
471 526
@@ -473,7 +528,8 @@ static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
473 return sprintf(page, "%s\n", buf); 528 return sprintf(page, "%s\n", buf);
474} 529}
475 530
476static ssize_t reipl_ccw_loadparm_store(struct kset *kset, 531static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
532 struct kobj_attribute *attr,
477 const char *buf, size_t len) 533 const char *buf, size_t len)
478{ 534{
479 int i, lp_len; 535 int i, lp_len;
@@ -500,7 +556,7 @@ static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
500 return len; 556 return len;
501} 557}
502 558
503static struct subsys_attribute sys_reipl_ccw_loadparm_attr = 559static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
504 __ATTR(loadparm, 0644, reipl_ccw_loadparm_show, 560 __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
505 reipl_ccw_loadparm_store); 561 reipl_ccw_loadparm_store);
506 562
@@ -539,7 +595,9 @@ static int reipl_set_type(enum ipl_type type)
539 595
540 switch(type) { 596 switch(type) {
541 case IPL_TYPE_CCW: 597 case IPL_TYPE_CCW:
542 if (MACHINE_IS_VM) 598 if (diag308_set_works)
599 reipl_method = REIPL_METHOD_CCW_DIAG;
600 else if (MACHINE_IS_VM)
543 reipl_method = REIPL_METHOD_CCW_VM; 601 reipl_method = REIPL_METHOD_CCW_VM;
544 else 602 else
545 reipl_method = REIPL_METHOD_CCW_CIO; 603 reipl_method = REIPL_METHOD_CCW_CIO;
@@ -568,13 +626,15 @@ static int reipl_set_type(enum ipl_type type)
568 return 0; 626 return 0;
569} 627}
570 628
571static ssize_t reipl_type_show(struct kset *kset, char *page) 629static ssize_t reipl_type_show(struct kobject *kobj,
630 struct kobj_attribute *attr, char *page)
572{ 631{
573 return sprintf(page, "%s\n", ipl_type_str(reipl_type)); 632 return sprintf(page, "%s\n", ipl_type_str(reipl_type));
574} 633}
575 634
576static ssize_t reipl_type_store(struct kset *kset, const char *buf, 635static ssize_t reipl_type_store(struct kobject *kobj,
577 size_t len) 636 struct kobj_attribute *attr,
637 const char *buf, size_t len)
578{ 638{
579 int rc = -EINVAL; 639 int rc = -EINVAL;
580 640
@@ -587,140 +647,12 @@ static ssize_t reipl_type_store(struct kset *kset, const char *buf,
587 return (rc != 0) ? rc : len; 647 return (rc != 0) ? rc : len;
588} 648}
589 649
590static struct subsys_attribute reipl_type_attr = 650static struct kobj_attribute reipl_type_attr =
591 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store); 651 __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
592
593static decl_subsys(reipl, NULL, NULL);
594
595/*
596 * dump section
597 */
598
599/* FCP dump device attributes */
600
601DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
602 dump_block_fcp->ipl_info.fcp.wwpn);
603DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
604 dump_block_fcp->ipl_info.fcp.lun);
605DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
606 dump_block_fcp->ipl_info.fcp.bootprog);
607DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
608 dump_block_fcp->ipl_info.fcp.br_lba);
609DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
610 dump_block_fcp->ipl_info.fcp.devno);
611
612static struct attribute *dump_fcp_attrs[] = {
613 &sys_dump_fcp_device_attr.attr,
614 &sys_dump_fcp_wwpn_attr.attr,
615 &sys_dump_fcp_lun_attr.attr,
616 &sys_dump_fcp_bootprog_attr.attr,
617 &sys_dump_fcp_br_lba_attr.attr,
618 NULL,
619};
620
621static struct attribute_group dump_fcp_attr_group = {
622 .name = IPL_FCP_STR,
623 .attrs = dump_fcp_attrs,
624};
625
626/* CCW dump device attributes */
627
628DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
629 dump_block_ccw->ipl_info.ccw.devno);
630
631static struct attribute *dump_ccw_attrs[] = {
632 &sys_dump_ccw_device_attr.attr,
633 NULL,
634};
635
636static struct attribute_group dump_ccw_attr_group = {
637 .name = IPL_CCW_STR,
638 .attrs = dump_ccw_attrs,
639};
640
641/* dump type */
642
643static int dump_set_type(enum dump_type type)
644{
645 if (!(dump_capabilities & type))
646 return -EINVAL;
647 switch(type) {
648 case DUMP_TYPE_CCW:
649 if (MACHINE_IS_VM)
650 dump_method = DUMP_METHOD_CCW_VM;
651 else if (diag308_set_works)
652 dump_method = DUMP_METHOD_CCW_DIAG;
653 else
654 dump_method = DUMP_METHOD_CCW_CIO;
655 break;
656 case DUMP_TYPE_FCP:
657 dump_method = DUMP_METHOD_FCP_DIAG;
658 break;
659 default:
660 dump_method = DUMP_METHOD_NONE;
661 }
662 dump_type = type;
663 return 0;
664}
665
666static ssize_t dump_type_show(struct kset *kset, char *page)
667{
668 return sprintf(page, "%s\n", dump_type_str(dump_type));
669}
670
671static ssize_t dump_type_store(struct kset *kset, const char *buf,
672 size_t len)
673{
674 int rc = -EINVAL;
675
676 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
677 rc = dump_set_type(DUMP_TYPE_NONE);
678 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
679 rc = dump_set_type(DUMP_TYPE_CCW);
680 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
681 rc = dump_set_type(DUMP_TYPE_FCP);
682 return (rc != 0) ? rc : len;
683}
684
685static struct subsys_attribute dump_type_attr =
686 __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
687
688static decl_subsys(dump, NULL, NULL);
689
690/*
691 * Shutdown actions section
692 */
693
694static decl_subsys(shutdown_actions, NULL, NULL);
695
696/* on panic */
697
698static ssize_t on_panic_show(struct kset *kset, char *page)
699{
700 return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
701}
702
703static ssize_t on_panic_store(struct kset *kset, const char *buf,
704 size_t len)
705{
706 if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
707 on_panic_action = SHUTDOWN_REIPL;
708 else if (strncmp(buf, SHUTDOWN_DUMP_STR,
709 strlen(SHUTDOWN_DUMP_STR)) == 0)
710 on_panic_action = SHUTDOWN_DUMP;
711 else if (strncmp(buf, SHUTDOWN_STOP_STR,
712 strlen(SHUTDOWN_STOP_STR)) == 0)
713 on_panic_action = SHUTDOWN_STOP;
714 else
715 return -EINVAL;
716
717 return len;
718}
719 652
720static struct subsys_attribute on_panic_attr = 653static struct kset *reipl_kset;
721 __ATTR(on_panic, 0644, on_panic_show, on_panic_store);
722 654
723void do_reipl(void) 655void reipl_run(struct shutdown_trigger *trigger)
724{ 656{
725 struct ccw_dev_id devid; 657 struct ccw_dev_id devid;
726 static char buf[100]; 658 static char buf[100];
@@ -729,8 +661,6 @@ void do_reipl(void)
729 switch (reipl_method) { 661 switch (reipl_method) {
730 case REIPL_METHOD_CCW_CIO: 662 case REIPL_METHOD_CCW_CIO:
731 devid.devno = reipl_block_ccw->ipl_info.ccw.devno; 663 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
732 if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
733 diag308(DIAG308_IPL, NULL);
734 devid.ssid = 0; 664 devid.ssid = 0;
735 reipl_ccw_dev(&devid); 665 reipl_ccw_dev(&devid);
736 break; 666 break;
@@ -771,98 +701,6 @@ void do_reipl(void)
771 default: 701 default:
772 break; 702 break;
773 } 703 }
774 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
775}
776
777static void do_dump(void)
778{
779 struct ccw_dev_id devid;
780 static char buf[100];
781
782 switch (dump_method) {
783 case DUMP_METHOD_CCW_CIO:
784 smp_send_stop();
785 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
786 devid.ssid = 0;
787 reipl_ccw_dev(&devid);
788 break;
789 case DUMP_METHOD_CCW_VM:
790 smp_send_stop();
791 sprintf(buf, "STORE STATUS");
792 __cpcmd(buf, NULL, 0, NULL);
793 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
794 __cpcmd(buf, NULL, 0, NULL);
795 break;
796 case DUMP_METHOD_CCW_DIAG:
797 diag308(DIAG308_SET, dump_block_ccw);
798 diag308(DIAG308_DUMP, NULL);
799 break;
800 case DUMP_METHOD_FCP_DIAG:
801 diag308(DIAG308_SET, dump_block_fcp);
802 diag308(DIAG308_DUMP, NULL);
803 break;
804 case DUMP_METHOD_NONE:
805 default:
806 return;
807 }
808 printk(KERN_EMERG "Dump failed!\n");
809}
810
811/* init functions */
812
813static int __init ipl_register_fcp_files(void)
814{
815 int rc;
816
817 rc = sysfs_create_group(&ipl_subsys.kobj,
818 &ipl_fcp_attr_group);
819 if (rc)
820 goto out;
821 rc = sysfs_create_bin_file(&ipl_subsys.kobj,
822 &ipl_parameter_attr);
823 if (rc)
824 goto out_ipl_parm;
825 rc = sysfs_create_bin_file(&ipl_subsys.kobj,
826 &ipl_scp_data_attr);
827 if (!rc)
828 goto out;
829
830 sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
831
832out_ipl_parm:
833 sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);
834out:
835 return rc;
836}
837
838static int __init ipl_init(void)
839{
840 int rc;
841
842 rc = firmware_register(&ipl_subsys);
843 if (rc)
844 return rc;
845 switch (ipl_info.type) {
846 case IPL_TYPE_CCW:
847 rc = sysfs_create_group(&ipl_subsys.kobj,
848 &ipl_ccw_attr_group);
849 break;
850 case IPL_TYPE_FCP:
851 case IPL_TYPE_FCP_DUMP:
852 rc = ipl_register_fcp_files();
853 break;
854 case IPL_TYPE_NSS:
855 rc = sysfs_create_group(&ipl_subsys.kobj,
856 &ipl_nss_attr_group);
857 break;
858 default:
859 rc = sysfs_create_group(&ipl_subsys.kobj,
860 &ipl_unknown_attr_group);
861 break;
862 }
863 if (rc)
864 firmware_unregister(&ipl_subsys);
865 return rc;
866} 704}
867 705
868static void __init reipl_probe(void) 706static void __init reipl_probe(void)
@@ -883,7 +721,7 @@ static int __init reipl_nss_init(void)
883 721
884 if (!MACHINE_IS_VM) 722 if (!MACHINE_IS_VM)
885 return 0; 723 return 0;
886 rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group); 724 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
887 if (rc) 725 if (rc)
888 return rc; 726 return rc;
889 strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); 727 strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
@@ -898,7 +736,7 @@ static int __init reipl_ccw_init(void)
898 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); 736 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
899 if (!reipl_block_ccw) 737 if (!reipl_block_ccw)
900 return -ENOMEM; 738 return -ENOMEM;
901 rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group); 739 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group);
902 if (rc) { 740 if (rc) {
903 free_page((unsigned long)reipl_block_ccw); 741 free_page((unsigned long)reipl_block_ccw);
904 return rc; 742 return rc;
@@ -907,6 +745,7 @@ static int __init reipl_ccw_init(void)
907 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; 745 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
908 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; 746 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
909 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;
910 /* check if read scp info worked and set loadparm */ 749 /* check if read scp info worked and set loadparm */
911 if (sclp_ipl_info.is_valid) 750 if (sclp_ipl_info.is_valid)
912 memcpy(reipl_block_ccw->ipl_info.ccw.load_param, 751 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
@@ -915,8 +754,7 @@ static int __init reipl_ccw_init(void)
915 /* read scp info failed: set empty loadparm (EBCDIC blanks) */ 754 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
916 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, 755 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
917 LOADPARM_LEN); 756 LOADPARM_LEN);
918 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */ 757 if (!MACHINE_IS_VM && !diag308_set_works)
919 if (!MACHINE_IS_VM)
920 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; 758 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
921 if (ipl_info.type == IPL_TYPE_CCW) 759 if (ipl_info.type == IPL_TYPE_CCW)
922 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; 760 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
@@ -936,7 +774,7 @@ static int __init reipl_fcp_init(void)
936 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); 774 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
937 if (!reipl_block_fcp) 775 if (!reipl_block_fcp)
938 return -ENOMEM; 776 return -ENOMEM;
939 rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group); 777 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_fcp_attr_group);
940 if (rc) { 778 if (rc) {
941 free_page((unsigned long)reipl_block_fcp); 779 free_page((unsigned long)reipl_block_fcp);
942 return rc; 780 return rc;
@@ -954,16 +792,16 @@ static int __init reipl_fcp_init(void)
954 return 0; 792 return 0;
955} 793}
956 794
957static int __init reipl_init(void) 795static int reipl_init(void)
958{ 796{
959 int rc; 797 int rc;
960 798
961 rc = firmware_register(&reipl_subsys); 799 reipl_kset = kset_create_and_add("reipl", NULL, firmware_kobj);
962 if (rc) 800 if (!reipl_kset)
963 return rc; 801 return -ENOMEM;
964 rc = subsys_create_file(&reipl_subsys, &reipl_type_attr); 802 rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
965 if (rc) { 803 if (rc) {
966 firmware_unregister(&reipl_subsys); 804 kset_unregister(reipl_kset);
967 return rc; 805 return rc;
968 } 806 }
969 rc = reipl_ccw_init(); 807 rc = reipl_ccw_init();
@@ -981,6 +819,140 @@ static int __init reipl_init(void)
981 return 0; 819 return 0;
982} 820}
983 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
984static int __init dump_ccw_init(void) 956static int __init dump_ccw_init(void)
985{ 957{
986 int rc; 958 int rc;
@@ -988,7 +960,7 @@ static int __init dump_ccw_init(void)
988 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); 960 dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
989 if (!dump_block_ccw) 961 if (!dump_block_ccw)
990 return -ENOMEM; 962 return -ENOMEM;
991 rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group); 963 rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
992 if (rc) { 964 if (rc) {
993 free_page((unsigned long)dump_block_ccw); 965 free_page((unsigned long)dump_block_ccw);
994 return rc; 966 return rc;
@@ -1012,7 +984,7 @@ static int __init dump_fcp_init(void)
1012 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); 984 dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
1013 if (!dump_block_fcp) 985 if (!dump_block_fcp)
1014 return -ENOMEM; 986 return -ENOMEM;
1015 rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group); 987 rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
1016 if (rc) { 988 if (rc) {
1017 free_page((unsigned long)dump_block_fcp); 989 free_page((unsigned long)dump_block_fcp);
1018 return rc; 990 return rc;
@@ -1026,33 +998,16 @@ static int __init dump_fcp_init(void)
1026 return 0; 998 return 0;
1027} 999}
1028 1000
1029#define SHUTDOWN_ON_PANIC_PRIO 0 1001static int dump_init(void)
1030
1031static int shutdown_on_panic_notify(struct notifier_block *self,
1032 unsigned long event, void *data)
1033{
1034 if (on_panic_action == SHUTDOWN_DUMP)
1035 do_dump();
1036 else if (on_panic_action == SHUTDOWN_REIPL)
1037 do_reipl();
1038 return NOTIFY_OK;
1039}
1040
1041static struct notifier_block shutdown_on_panic_nb = {
1042 .notifier_call = shutdown_on_panic_notify,
1043 .priority = SHUTDOWN_ON_PANIC_PRIO
1044};
1045
1046static int __init dump_init(void)
1047{ 1002{
1048 int rc; 1003 int rc;
1049 1004
1050 rc = firmware_register(&dump_subsys); 1005 dump_kset = kset_create_and_add("dump", NULL, firmware_kobj);
1051 if (rc) 1006 if (!dump_kset)
1052 return rc; 1007 return -ENOMEM;
1053 rc = subsys_create_file(&dump_subsys, &dump_type_attr); 1008 rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
1054 if (rc) { 1009 if (rc) {
1055 firmware_unregister(&dump_subsys); 1010 kset_unregister(dump_kset);
1056 return rc; 1011 return rc;
1057 } 1012 }
1058 rc = dump_ccw_init(); 1013 rc = dump_ccw_init();
@@ -1065,46 +1020,381 @@ static int __init dump_init(void)
1065 return 0; 1020 return 0;
1066} 1021}
1067 1022
1068static 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)
1069{ 1083{
1070 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}
1071 1091
1072 rc = firmware_register(&shutdown_actions_subsys); 1092static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
1073 if (rc) 1093 vmcmd_run, vmcmd_init};
1074 return rc; 1094
1075 rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr); 1095/*
1076 if (rc) { 1096 * stop shutdown action: Stop Linux on shutdown.
1077 firmware_unregister(&shutdown_actions_subsys); 1097 */
1078 return rc; 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 (;;);
1079 } 1106 }
1080 atomic_notifier_chain_register(&panic_notifier_list,
1081 &shutdown_on_panic_nb);
1082 return 0;
1083} 1107}
1084 1108
1085static int __init s390_ipl_init(void) 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)
1086{ 1126{
1087 int rc; 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}
1088 1139
1089 sclp_get_ipl_info(&sclp_ipl_info); 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}
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{
1255 shutdown_actions_kset = kset_create_and_add("shutdown_actions", NULL,
1256 firmware_kobj);
1257 if (!shutdown_actions_kset)
1258 goto fail;
1259 if (sysfs_create_file(&shutdown_actions_kset->kobj,
1260 &on_reboot_attr.attr))
1261 goto fail;
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;
1286 }
1287}
1288
1289static int __init s390_ipl_init(void)
1290{
1090 reipl_probe(); 1291 reipl_probe();
1091 rc = ipl_init(); 1292 sclp_get_ipl_info(&sclp_ipl_info);
1092 if (rc) 1293 shutdown_actions_init();
1093 return rc; 1294 shutdown_triggers_init();
1094 rc = reipl_init();
1095 if (rc)
1096 return rc;
1097 rc = dump_init();
1098 if (rc)
1099 return rc;
1100 rc = shutdown_actions_init();
1101 if (rc)
1102 return rc;
1103 return 0; 1295 return 0;
1104} 1296}
1105 1297
1106__initcall(s390_ipl_init); 1298__initcall(s390_ipl_init);
1107 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
1108void __init ipl_save_parameters(void) 1398void __init ipl_save_parameters(void)
1109{ 1399{
1110 struct cio_iplinfo iplinfo; 1400 struct cio_iplinfo iplinfo;
@@ -1185,3 +1475,4 @@ void s390_reset_system(void)
1185 1475
1186 do_reset_calls(); 1476 do_reset_calls();
1187} 1477}
1478