aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ipl.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-12-04 09:40:26 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-04 09:40:26 -0500
commit15e9b586e0bd3692e2a21c5be178810d9d32214e (patch)
tree8bcf2c9b3780281c9562eab965e3ca6ba64e5bc0 /arch/s390/kernel/ipl.c
parent2254f5a7779452395e37ea2f7d6e1a550d34e678 (diff)
[S390] Reset infrastructure for re-IPL.
In case of re-IPL and diag308 doesn't work we have to reset all devices manually and wait synchronously that each reset finished. This patch adds the necessary infrastucture and the first exploiter of it. Subsystems that need to add a function that needs to be called at re-IPL may register/unregister this function via struct reset_call { struct reset_call *next; void (*fn)(void); }; void register_reset_call(struct reset_call *reset); void unregister_reset_call(struct reset_call *reset); When the registered function get called the context is: - all cpus beside the current one are stopped - all machine checks and interrupts are disabled - prefixing is disabled - a default machine check handler is available for use The registered functions may not take any locks are sleep. For the common I/O layer part of this patch: Introduce a reset_call css_reset that does the following: - clear all subchannels - perform a rchp on all channel paths and wait for the resulting machine checks This replaces the calls to clear_all_subchannels() and cio_reset_channel_paths() for kexec and ccw reipl. reipl_ccw_dev() now uses reipl_find_schid() to determine the subchannel id for a given device id. Also remove cio_reset_channel_paths() and friends since they are not needed anymore. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r--arch/s390/kernel/ipl.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index ec127826f221..77f4aff630fe 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -19,6 +19,7 @@
19#include <asm/cpcmd.h> 19#include <asm/cpcmd.h>
20#include <asm/cio.h> 20#include <asm/cio.h>
21#include <asm/ebcdic.h> 21#include <asm/ebcdic.h>
22#include <asm/reset.h>
22 23
23#define IPL_PARM_BLOCK_VERSION 0 24#define IPL_PARM_BLOCK_VERSION 0
24#define LOADPARM_LEN 8 25#define LOADPARM_LEN 8
@@ -1024,3 +1025,56 @@ static int __init s390_ipl_init(void)
1024} 1025}
1025 1026
1026__initcall(s390_ipl_init); 1027__initcall(s390_ipl_init);
1028
1029static LIST_HEAD(rcall);
1030static DEFINE_MUTEX(rcall_mutex);
1031
1032void register_reset_call(struct reset_call *reset)
1033{
1034 mutex_lock(&rcall_mutex);
1035 list_add(&reset->list, &rcall);
1036 mutex_unlock(&rcall_mutex);
1037}
1038EXPORT_SYMBOL_GPL(register_reset_call);
1039
1040void unregister_reset_call(struct reset_call *reset)
1041{
1042 mutex_lock(&rcall_mutex);
1043 list_del(&reset->list);
1044 mutex_unlock(&rcall_mutex);
1045}
1046EXPORT_SYMBOL_GPL(unregister_reset_call);
1047
1048static void do_reset_calls(void)
1049{
1050 struct reset_call *reset;
1051
1052 list_for_each_entry(reset, &rcall, list)
1053 reset->fn();
1054}
1055
1056extern void reset_mcck_handler(void);
1057
1058void s390_reset_system(void)
1059{
1060 struct _lowcore *lc;
1061
1062 /* Disable all interrupts/machine checks */
1063 __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
1064
1065 /* Stack for interrupt/machine check handler */
1066 lc = (struct _lowcore *)(unsigned long) store_prefix();
1067 lc->panic_stack = S390_lowcore.panic_stack;
1068
1069 /* Disable prefixing */
1070 set_prefix(0);
1071
1072 /* Disable lowcore protection */
1073 __ctl_clear_bit(0,28);
1074
1075 /* Set new machine check handler */
1076 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
1077 S390_lowcore.mcck_new_psw.addr =
1078 PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
1079 do_reset_calls();
1080}