Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * signal quiesce handler |
3 | * | |
a53c8fab | 4 | * Copyright IBM Corp. 1999, 2004 |
1da177e4 LT |
5 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> |
6 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | |
7 | */ | |
8 | ||
1da177e4 LT |
9 | #include <linux/module.h> |
10 | #include <linux/types.h> | |
11 | #include <linux/cpumask.h> | |
12 | #include <linux/smp.h> | |
13 | #include <linux/init.h> | |
83cc5ed3 | 14 | #include <linux/reboot.h> |
60063497 | 15 | #include <linux/atomic.h> |
1da177e4 | 16 | #include <asm/ptrace.h> |
188596fa | 17 | #include <asm/smp.h> |
1da177e4 LT |
18 | |
19 | #include "sclp.h" | |
20 | ||
8b94c1ed MS |
21 | static void (*old_machine_restart)(char *); |
22 | static void (*old_machine_halt)(void); | |
23 | static void (*old_machine_power_off)(void); | |
24 | ||
1da177e4 | 25 | /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ |
8b94c1ed | 26 | static void do_machine_quiesce(void) |
1da177e4 LT |
27 | { |
28 | psw_t quiesce_psw; | |
29 | ||
c6b5b847 | 30 | smp_send_stop(); |
b50511e4 MS |
31 | quiesce_psw.mask = |
32 | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT; | |
1da177e4 LT |
33 | quiesce_psw.addr = 0xfff; |
34 | __load_psw(quiesce_psw); | |
35 | } | |
1da177e4 | 36 | |
1da177e4 | 37 | /* Handler for quiesce event. Start shutdown procedure. */ |
8b94c1ed | 38 | static void sclp_quiesce_handler(struct evbuf_header *evbuf) |
1da177e4 | 39 | { |
8b94c1ed MS |
40 | if (_machine_restart != (void *) do_machine_quiesce) { |
41 | old_machine_restart = _machine_restart; | |
42 | old_machine_halt = _machine_halt; | |
43 | old_machine_power_off = _machine_power_off; | |
44 | _machine_restart = (void *) do_machine_quiesce; | |
45 | _machine_halt = do_machine_quiesce; | |
46 | _machine_power_off = do_machine_quiesce; | |
47 | } | |
1da177e4 LT |
48 | ctrl_alt_del(); |
49 | } | |
50 | ||
8b94c1ed MS |
51 | /* Undo machine restart/halt/power_off modification on resume */ |
52 | static void sclp_quiesce_pm_event(struct sclp_register *reg, | |
53 | enum sclp_pm_event sclp_pm_event) | |
54 | { | |
55 | switch (sclp_pm_event) { | |
56 | case SCLP_PM_EVENT_RESTORE: | |
57 | if (old_machine_restart) { | |
58 | _machine_restart = old_machine_restart; | |
59 | _machine_halt = old_machine_halt; | |
60 | _machine_power_off = old_machine_power_off; | |
61 | old_machine_restart = NULL; | |
62 | old_machine_halt = NULL; | |
63 | old_machine_power_off = NULL; | |
64 | } | |
65 | break; | |
66 | case SCLP_PM_EVENT_FREEZE: | |
67 | case SCLP_PM_EVENT_THAW: | |
68 | break; | |
69 | } | |
70 | } | |
71 | ||
1da177e4 | 72 | static struct sclp_register sclp_quiesce_event = { |
6d4740c8 | 73 | .receive_mask = EVTYP_SIGQUIESCE_MASK, |
8b94c1ed MS |
74 | .receiver_fn = sclp_quiesce_handler, |
75 | .pm_event_fn = sclp_quiesce_pm_event | |
1da177e4 LT |
76 | }; |
77 | ||
78 | /* Initialize quiesce driver. */ | |
8b94c1ed | 79 | static int __init sclp_quiesce_init(void) |
1da177e4 | 80 | { |
a12c53f4 | 81 | return sclp_register(&sclp_quiesce_event); |
1da177e4 LT |
82 | } |
83 | ||
84 | module_init(sclp_quiesce_init); |