Merge branches 'pm-cpufreq', 'pm-cpuidle', 'pm-devfreq', 'pm-opp' and 'pm-tools'
[linux-drm-fsl-dcu.git] / drivers / xen / manage.c
1 /*
2  * Handle extern requests for shutdown, reboot and sysrq
3  */
4
5 #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
6
7 #include <linux/kernel.h>
8 #include <linux/err.h>
9 #include <linux/slab.h>
10 #include <linux/reboot.h>
11 #include <linux/sysrq.h>
12 #include <linux/stop_machine.h>
13 #include <linux/freezer.h>
14 #include <linux/syscore_ops.h>
15 #include <linux/export.h>
16
17 #include <xen/xen.h>
18 #include <xen/xenbus.h>
19 #include <xen/grant_table.h>
20 #include <xen/events.h>
21 #include <xen/hvc-console.h>
22 #include <xen/xen-ops.h>
23
24 #include <asm/xen/hypercall.h>
25 #include <asm/xen/page.h>
26 #include <asm/xen/hypervisor.h>
27
28 enum shutdown_state {
29         SHUTDOWN_INVALID = -1,
30         SHUTDOWN_POWEROFF = 0,
31         SHUTDOWN_SUSPEND = 2,
32         /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
33            report a crash, not be instructed to crash!
34            HALT is the same as POWEROFF, as far as we're concerned.  The tools use
35            the distinction when we return the reason code to them.  */
36          SHUTDOWN_HALT = 4,
37 };
38
39 /* Ignore multiple shutdown requests. */
40 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
41
42 struct suspend_info {
43         int cancelled;
44 };
45
46 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
47
48 void xen_resume_notifier_register(struct notifier_block *nb)
49 {
50         raw_notifier_chain_register(&xen_resume_notifier, nb);
51 }
52 EXPORT_SYMBOL_GPL(xen_resume_notifier_register);
53
54 void xen_resume_notifier_unregister(struct notifier_block *nb)
55 {
56         raw_notifier_chain_unregister(&xen_resume_notifier, nb);
57 }
58 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
59
60 #ifdef CONFIG_HIBERNATE_CALLBACKS
61 static int xen_suspend(void *data)
62 {
63         struct suspend_info *si = data;
64         int err;
65
66         BUG_ON(!irqs_disabled());
67
68         err = syscore_suspend();
69         if (err) {
70                 pr_err("%s: system core suspend failed: %d\n", __func__, err);
71                 return err;
72         }
73
74         gnttab_suspend();
75         xen_arch_pre_suspend();
76
77         /*
78          * This hypercall returns 1 if suspend was cancelled
79          * or the domain was merely checkpointed, and 0 if it
80          * is resuming in a new domain.
81          */
82         si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
83                                            ? virt_to_mfn(xen_start_info)
84                                            : 0);
85
86         xen_arch_post_suspend(si->cancelled);
87         gnttab_resume();
88
89         if (!si->cancelled) {
90                 xen_irq_resume();
91                 xen_timer_resume();
92         }
93
94         syscore_resume();
95
96         return 0;
97 }
98
99 static void do_suspend(void)
100 {
101         int err;
102         struct suspend_info si;
103
104         shutting_down = SHUTDOWN_SUSPEND;
105
106         err = freeze_processes();
107         if (err) {
108                 pr_err("%s: freeze processes failed %d\n", __func__, err);
109                 goto out;
110         }
111
112         err = freeze_kernel_threads();
113         if (err) {
114                 pr_err("%s: freeze kernel threads failed %d\n", __func__, err);
115                 goto out_thaw;
116         }
117
118         err = dpm_suspend_start(PMSG_FREEZE);
119         if (err) {
120                 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
121                 goto out_thaw;
122         }
123
124         printk(KERN_DEBUG "suspending xenstore...\n");
125         xs_suspend();
126
127         err = dpm_suspend_end(PMSG_FREEZE);
128         if (err) {
129                 pr_err("dpm_suspend_end failed: %d\n", err);
130                 si.cancelled = 0;
131                 goto out_resume;
132         }
133
134         si.cancelled = 1;
135
136         err = stop_machine(xen_suspend, &si, cpumask_of(0));
137
138         /* Resume console as early as possible. */
139         if (!si.cancelled)
140                 xen_console_resume();
141
142         raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
143
144         dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
145
146         if (err) {
147                 pr_err("failed to start xen_suspend: %d\n", err);
148                 si.cancelled = 1;
149         }
150
151 out_resume:
152         if (!si.cancelled) {
153                 xen_arch_resume();
154                 xs_resume();
155         } else
156                 xs_suspend_cancel();
157
158         dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
159
160 out_thaw:
161         thaw_processes();
162 out:
163         shutting_down = SHUTDOWN_INVALID;
164 }
165 #endif  /* CONFIG_HIBERNATE_CALLBACKS */
166
167 struct shutdown_handler {
168         const char *command;
169         void (*cb)(void);
170 };
171
172 static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
173 {
174         switch (code) {
175         case SYS_DOWN:
176         case SYS_HALT:
177         case SYS_POWER_OFF:
178                 shutting_down = SHUTDOWN_POWEROFF;
179         default:
180                 break;
181         }
182         return NOTIFY_DONE;
183 }
184 static void do_poweroff(void)
185 {
186         switch (system_state) {
187         case SYSTEM_BOOTING:
188                 orderly_poweroff(true);
189                 break;
190         case SYSTEM_RUNNING:
191                 orderly_poweroff(false);
192                 break;
193         default:
194                 /* Don't do it when we are halting/rebooting. */
195                 pr_info("Ignoring Xen toolstack shutdown.\n");
196                 break;
197         }
198 }
199
200 static void do_reboot(void)
201 {
202         shutting_down = SHUTDOWN_POWEROFF; /* ? */
203         ctrl_alt_del();
204 }
205
206 static void shutdown_handler(struct xenbus_watch *watch,
207                              const char **vec, unsigned int len)
208 {
209         char *str;
210         struct xenbus_transaction xbt;
211         int err;
212         static struct shutdown_handler handlers[] = {
213                 { "poweroff",   do_poweroff },
214                 { "halt",       do_poweroff },
215                 { "reboot",     do_reboot   },
216 #ifdef CONFIG_HIBERNATE_CALLBACKS
217                 { "suspend",    do_suspend  },
218 #endif
219                 {NULL, NULL},
220         };
221         static struct shutdown_handler *handler;
222
223         if (shutting_down != SHUTDOWN_INVALID)
224                 return;
225
226  again:
227         err = xenbus_transaction_start(&xbt);
228         if (err)
229                 return;
230
231         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
232         /* Ignore read errors and empty reads. */
233         if (XENBUS_IS_ERR_READ(str)) {
234                 xenbus_transaction_end(xbt, 1);
235                 return;
236         }
237
238         for (handler = &handlers[0]; handler->command; handler++) {
239                 if (strcmp(str, handler->command) == 0)
240                         break;
241         }
242
243         /* Only acknowledge commands which we are prepared to handle. */
244         if (handler->cb)
245                 xenbus_write(xbt, "control", "shutdown", "");
246
247         err = xenbus_transaction_end(xbt, 0);
248         if (err == -EAGAIN) {
249                 kfree(str);
250                 goto again;
251         }
252
253         if (handler->cb) {
254                 handler->cb();
255         } else {
256                 pr_info("Ignoring shutdown request: %s\n", str);
257                 shutting_down = SHUTDOWN_INVALID;
258         }
259
260         kfree(str);
261 }
262
263 #ifdef CONFIG_MAGIC_SYSRQ
264 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
265                           unsigned int len)
266 {
267         char sysrq_key = '\0';
268         struct xenbus_transaction xbt;
269         int err;
270
271  again:
272         err = xenbus_transaction_start(&xbt);
273         if (err)
274                 return;
275         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
276                 pr_err("Unable to read sysrq code in control/sysrq\n");
277                 xenbus_transaction_end(xbt, 1);
278                 return;
279         }
280
281         if (sysrq_key != '\0')
282                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
283
284         err = xenbus_transaction_end(xbt, 0);
285         if (err == -EAGAIN)
286                 goto again;
287
288         if (sysrq_key != '\0')
289                 handle_sysrq(sysrq_key);
290 }
291
292 static struct xenbus_watch sysrq_watch = {
293         .node = "control/sysrq",
294         .callback = sysrq_handler
295 };
296 #endif
297
298 static struct xenbus_watch shutdown_watch = {
299         .node = "control/shutdown",
300         .callback = shutdown_handler
301 };
302
303 static struct notifier_block xen_reboot_nb = {
304         .notifier_call = poweroff_nb,
305 };
306
307 static int setup_shutdown_watcher(void)
308 {
309         int err;
310
311         err = register_xenbus_watch(&shutdown_watch);
312         if (err) {
313                 pr_err("Failed to set shutdown watcher\n");
314                 return err;
315         }
316
317
318 #ifdef CONFIG_MAGIC_SYSRQ
319         err = register_xenbus_watch(&sysrq_watch);
320         if (err) {
321                 pr_err("Failed to set sysrq watcher\n");
322                 return err;
323         }
324 #endif
325
326         return 0;
327 }
328
329 static int shutdown_event(struct notifier_block *notifier,
330                           unsigned long event,
331                           void *data)
332 {
333         setup_shutdown_watcher();
334         return NOTIFY_DONE;
335 }
336
337 int xen_setup_shutdown_event(void)
338 {
339         static struct notifier_block xenstore_notifier = {
340                 .notifier_call = shutdown_event
341         };
342
343         if (!xen_domain())
344                 return -ENODEV;
345         register_xenstore_notifier(&xenstore_notifier);
346         register_reboot_notifier(&xen_reboot_nb);
347
348         return 0;
349 }
350 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
351
352 subsys_initcall(xen_setup_shutdown_event);