diff options
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index a689070be28..48c71020636 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -45,11 +45,13 @@ | |||
45 | * - halt | 45 | * - halt |
46 | * - power off | 46 | * - power off |
47 | * - reipl | 47 | * - reipl |
48 | * - restart | ||
48 | */ | 49 | */ |
49 | #define ON_PANIC_STR "on_panic" | 50 | #define ON_PANIC_STR "on_panic" |
50 | #define ON_HALT_STR "on_halt" | 51 | #define ON_HALT_STR "on_halt" |
51 | #define ON_POFF_STR "on_poff" | 52 | #define ON_POFF_STR "on_poff" |
52 | #define ON_REIPL_STR "on_reboot" | 53 | #define ON_REIPL_STR "on_reboot" |
54 | #define ON_RESTART_STR "on_restart" | ||
53 | 55 | ||
54 | struct shutdown_action; | 56 | struct shutdown_action; |
55 | struct shutdown_trigger { | 57 | struct shutdown_trigger { |
@@ -1218,7 +1220,7 @@ static int __init reipl_fcp_init(void) | |||
1218 | /* sysfs: create fcp kset for mixing attr group and bin attrs */ | 1220 | /* sysfs: create fcp kset for mixing attr group and bin attrs */ |
1219 | reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL, | 1221 | reipl_fcp_kset = kset_create_and_add(IPL_FCP_STR, NULL, |
1220 | &reipl_kset->kobj); | 1222 | &reipl_kset->kobj); |
1221 | if (!reipl_kset) { | 1223 | if (!reipl_fcp_kset) { |
1222 | free_page((unsigned long) reipl_block_fcp); | 1224 | free_page((unsigned long) reipl_block_fcp); |
1223 | return -ENOMEM; | 1225 | return -ENOMEM; |
1224 | } | 1226 | } |
@@ -1544,17 +1546,20 @@ static char vmcmd_on_reboot[128]; | |||
1544 | static char vmcmd_on_panic[128]; | 1546 | static char vmcmd_on_panic[128]; |
1545 | static char vmcmd_on_halt[128]; | 1547 | static char vmcmd_on_halt[128]; |
1546 | static char vmcmd_on_poff[128]; | 1548 | static char vmcmd_on_poff[128]; |
1549 | static char vmcmd_on_restart[128]; | ||
1547 | 1550 | ||
1548 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot); | 1551 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot); |
1549 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic); | 1552 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic); |
1550 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt); | 1553 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt); |
1551 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff); | 1554 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff); |
1555 | DEFINE_IPL_ATTR_STR_RW(vmcmd, on_restart, "%s\n", "%s\n", vmcmd_on_restart); | ||
1552 | 1556 | ||
1553 | static struct attribute *vmcmd_attrs[] = { | 1557 | static struct attribute *vmcmd_attrs[] = { |
1554 | &sys_vmcmd_on_reboot_attr.attr, | 1558 | &sys_vmcmd_on_reboot_attr.attr, |
1555 | &sys_vmcmd_on_panic_attr.attr, | 1559 | &sys_vmcmd_on_panic_attr.attr, |
1556 | &sys_vmcmd_on_halt_attr.attr, | 1560 | &sys_vmcmd_on_halt_attr.attr, |
1557 | &sys_vmcmd_on_poff_attr.attr, | 1561 | &sys_vmcmd_on_poff_attr.attr, |
1562 | &sys_vmcmd_on_restart_attr.attr, | ||
1558 | NULL, | 1563 | NULL, |
1559 | }; | 1564 | }; |
1560 | 1565 | ||
@@ -1576,6 +1581,8 @@ static void vmcmd_run(struct shutdown_trigger *trigger) | |||
1576 | cmd = vmcmd_on_halt; | 1581 | cmd = vmcmd_on_halt; |
1577 | else if (strcmp(trigger->name, ON_POFF_STR) == 0) | 1582 | else if (strcmp(trigger->name, ON_POFF_STR) == 0) |
1578 | cmd = vmcmd_on_poff; | 1583 | cmd = vmcmd_on_poff; |
1584 | else if (strcmp(trigger->name, ON_RESTART_STR) == 0) | ||
1585 | cmd = vmcmd_on_restart; | ||
1579 | else | 1586 | else |
1580 | return; | 1587 | return; |
1581 | 1588 | ||
@@ -1611,7 +1618,8 @@ static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR, | |||
1611 | 1618 | ||
1612 | static void stop_run(struct shutdown_trigger *trigger) | 1619 | static void stop_run(struct shutdown_trigger *trigger) |
1613 | { | 1620 | { |
1614 | if (strcmp(trigger->name, ON_PANIC_STR) == 0) | 1621 | if (strcmp(trigger->name, ON_PANIC_STR) == 0 || |
1622 | strcmp(trigger->name, ON_RESTART_STR) == 0) | ||
1615 | disabled_wait((unsigned long) __builtin_return_address(0)); | 1623 | disabled_wait((unsigned long) __builtin_return_address(0)); |
1616 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) | 1624 | while (sigp(smp_processor_id(), sigp_stop) == sigp_busy) |
1617 | cpu_relax(); | 1625 | cpu_relax(); |
@@ -1707,6 +1715,34 @@ static void do_panic(void) | |||
1707 | stop_run(&on_panic_trigger); | 1715 | stop_run(&on_panic_trigger); |
1708 | } | 1716 | } |
1709 | 1717 | ||
1718 | /* on restart */ | ||
1719 | |||
1720 | static struct shutdown_trigger on_restart_trigger = {ON_RESTART_STR, | ||
1721 | &stop_action}; | ||
1722 | |||
1723 | static ssize_t on_restart_show(struct kobject *kobj, | ||
1724 | struct kobj_attribute *attr, char *page) | ||
1725 | { | ||
1726 | return sprintf(page, "%s\n", on_restart_trigger.action->name); | ||
1727 | } | ||
1728 | |||
1729 | static ssize_t on_restart_store(struct kobject *kobj, | ||
1730 | struct kobj_attribute *attr, | ||
1731 | const char *buf, size_t len) | ||
1732 | { | ||
1733 | return set_trigger(buf, &on_restart_trigger, len); | ||
1734 | } | ||
1735 | |||
1736 | static struct kobj_attribute on_restart_attr = | ||
1737 | __ATTR(on_restart, 0644, on_restart_show, on_restart_store); | ||
1738 | |||
1739 | void do_restart(void) | ||
1740 | { | ||
1741 | smp_send_stop(); | ||
1742 | on_restart_trigger.action->fn(&on_restart_trigger); | ||
1743 | stop_run(&on_restart_trigger); | ||
1744 | } | ||
1745 | |||
1710 | /* on halt */ | 1746 | /* on halt */ |
1711 | 1747 | ||
1712 | static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action}; | 1748 | static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action}; |
@@ -1783,7 +1819,9 @@ static void __init shutdown_triggers_init(void) | |||
1783 | if (sysfs_create_file(&shutdown_actions_kset->kobj, | 1819 | if (sysfs_create_file(&shutdown_actions_kset->kobj, |
1784 | &on_poff_attr.attr)) | 1820 | &on_poff_attr.attr)) |
1785 | goto fail; | 1821 | goto fail; |
1786 | 1822 | if (sysfs_create_file(&shutdown_actions_kset->kobj, | |
1823 | &on_restart_attr.attr)) | ||
1824 | goto fail; | ||
1787 | return; | 1825 | return; |
1788 | fail: | 1826 | fail: |
1789 | panic("shutdown_triggers_init failed\n"); | 1827 | panic("shutdown_triggers_init failed\n"); |
@@ -1959,6 +1997,12 @@ static void do_reset_calls(void) | |||
1959 | { | 1997 | { |
1960 | struct reset_call *reset; | 1998 | struct reset_call *reset; |
1961 | 1999 | ||
2000 | #ifdef CONFIG_64BIT | ||
2001 | if (diag308_set_works) { | ||
2002 | diag308_reset(); | ||
2003 | return; | ||
2004 | } | ||
2005 | #endif | ||
1962 | list_for_each_entry(reset, &rcall, list) | 2006 | list_for_each_entry(reset, &rcall, list) |
1963 | reset->fn(); | 2007 | reset->fn(); |
1964 | } | 2008 | } |