diff options
Diffstat (limited to 'drivers/s390/char/sclp_quiesce.c')
-rw-r--r-- | drivers/s390/char/sclp_quiesce.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c index 84c191c1cd62..05909a7df8b3 100644 --- a/drivers/s390/char/sclp_quiesce.c +++ b/drivers/s390/char/sclp_quiesce.c | |||
@@ -20,9 +20,12 @@ | |||
20 | 20 | ||
21 | #include "sclp.h" | 21 | #include "sclp.h" |
22 | 22 | ||
23 | static void (*old_machine_restart)(char *); | ||
24 | static void (*old_machine_halt)(void); | ||
25 | static void (*old_machine_power_off)(void); | ||
26 | |||
23 | /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ | 27 | /* Shutdown handler. Signal completion of shutdown by loading special PSW. */ |
24 | static void | 28 | static void do_machine_quiesce(void) |
25 | do_machine_quiesce(void) | ||
26 | { | 29 | { |
27 | psw_t quiesce_psw; | 30 | psw_t quiesce_psw; |
28 | 31 | ||
@@ -33,23 +36,48 @@ do_machine_quiesce(void) | |||
33 | } | 36 | } |
34 | 37 | ||
35 | /* Handler for quiesce event. Start shutdown procedure. */ | 38 | /* Handler for quiesce event. Start shutdown procedure. */ |
36 | static void | 39 | static void sclp_quiesce_handler(struct evbuf_header *evbuf) |
37 | sclp_quiesce_handler(struct evbuf_header *evbuf) | ||
38 | { | 40 | { |
39 | _machine_restart = (void *) do_machine_quiesce; | 41 | if (_machine_restart != (void *) do_machine_quiesce) { |
40 | _machine_halt = do_machine_quiesce; | 42 | old_machine_restart = _machine_restart; |
41 | _machine_power_off = do_machine_quiesce; | 43 | old_machine_halt = _machine_halt; |
44 | old_machine_power_off = _machine_power_off; | ||
45 | _machine_restart = (void *) do_machine_quiesce; | ||
46 | _machine_halt = do_machine_quiesce; | ||
47 | _machine_power_off = do_machine_quiesce; | ||
48 | } | ||
42 | ctrl_alt_del(); | 49 | ctrl_alt_del(); |
43 | } | 50 | } |
44 | 51 | ||
52 | /* Undo machine restart/halt/power_off modification on resume */ | ||
53 | static void sclp_quiesce_pm_event(struct sclp_register *reg, | ||
54 | enum sclp_pm_event sclp_pm_event) | ||
55 | { | ||
56 | switch (sclp_pm_event) { | ||
57 | case SCLP_PM_EVENT_RESTORE: | ||
58 | if (old_machine_restart) { | ||
59 | _machine_restart = old_machine_restart; | ||
60 | _machine_halt = old_machine_halt; | ||
61 | _machine_power_off = old_machine_power_off; | ||
62 | old_machine_restart = NULL; | ||
63 | old_machine_halt = NULL; | ||
64 | old_machine_power_off = NULL; | ||
65 | } | ||
66 | break; | ||
67 | case SCLP_PM_EVENT_FREEZE: | ||
68 | case SCLP_PM_EVENT_THAW: | ||
69 | break; | ||
70 | } | ||
71 | } | ||
72 | |||
45 | static struct sclp_register sclp_quiesce_event = { | 73 | static struct sclp_register sclp_quiesce_event = { |
46 | .receive_mask = EVTYP_SIGQUIESCE_MASK, | 74 | .receive_mask = EVTYP_SIGQUIESCE_MASK, |
47 | .receiver_fn = sclp_quiesce_handler | 75 | .receiver_fn = sclp_quiesce_handler, |
76 | .pm_event_fn = sclp_quiesce_pm_event | ||
48 | }; | 77 | }; |
49 | 78 | ||
50 | /* Initialize quiesce driver. */ | 79 | /* Initialize quiesce driver. */ |
51 | static int __init | 80 | static int __init sclp_quiesce_init(void) |
52 | sclp_quiesce_init(void) | ||
53 | { | 81 | { |
54 | return sclp_register(&sclp_quiesce_event); | 82 | return sclp_register(&sclp_quiesce_event); |
55 | } | 83 | } |