Merge tag 'iio-fixes-for-3.16a' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.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_console_resume();
92                 xen_timer_resume();
93         }
94
95         syscore_resume();
96
97         return 0;
98 }
99
100 static void do_suspend(void)
101 {
102         int err;
103         struct suspend_info si;
104
105         shutting_down = SHUTDOWN_SUSPEND;
106
107 #ifdef CONFIG_PREEMPT
108         /* If the kernel is preemptible, we need to freeze all the processes
109            to prevent them from being in the middle of a pagetable update
110            during suspend. */
111         err = freeze_processes();
112         if (err) {
113                 pr_err("%s: freeze failed %d\n", __func__, err);
114                 goto out;
115         }
116 #endif
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         raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
139
140         dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
141
142         if (err) {
143                 pr_err("failed to start xen_suspend: %d\n", err);
144                 si.cancelled = 1;
145         }
146
147 out_resume:
148         if (!si.cancelled) {
149                 xen_arch_resume();
150                 xs_resume();
151         } else
152                 xs_suspend_cancel();
153
154         dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
155
156 out_thaw:
157 #ifdef CONFIG_PREEMPT
158         thaw_processes();
159 out:
160 #endif
161         shutting_down = SHUTDOWN_INVALID;
162 }
163 #endif  /* CONFIG_HIBERNATE_CALLBACKS */
164
165 struct shutdown_handler {
166         const char *command;
167         void (*cb)(void);
168 };
169
170 static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused)
171 {
172         switch (code) {
173         case SYS_DOWN:
174         case SYS_HALT:
175         case SYS_POWER_OFF:
176                 shutting_down = SHUTDOWN_POWEROFF;
177         default:
178                 break;
179         }
180         return NOTIFY_DONE;
181 }
182 static void do_poweroff(void)
183 {
184         switch (system_state) {
185         case SYSTEM_BOOTING:
186                 orderly_poweroff(true);
187                 break;
188         case SYSTEM_RUNNING:
189                 orderly_poweroff(false);
190                 break;
191         default:
192                 /* Don't do it when we are halting/rebooting. */
193                 pr_info("Ignoring Xen toolstack shutdown.\n");
194                 break;
195         }
196 }
197
198 static void do_reboot(void)
199 {
200         shutting_down = SHUTDOWN_POWEROFF; /* ? */
201         ctrl_alt_del();
202 }
203
204 static void shutdown_handler(struct xenbus_watch *watch,
205                              const char **vec, unsigned int len)
206 {
207         char *str;
208         struct xenbus_transaction xbt;
209         int err;
210         static struct shutdown_handler handlers[] = {
211                 { "poweroff",   do_poweroff },
212                 { "halt",       do_poweroff },
213                 { "reboot",     do_reboot   },
214 #ifdef CONFIG_HIBERNATE_CALLBACKS
215                 { "suspend",    do_suspend  },
216 #endif
217                 {NULL, NULL},
218         };
219         static struct shutdown_handler *handler;
220
221         if (shutting_down != SHUTDOWN_INVALID)
222                 return;
223
224  again:
225         err = xenbus_transaction_start(&xbt);
226         if (err)
227                 return;
228
229         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
230         /* Ignore read errors and empty reads. */
231         if (XENBUS_IS_ERR_READ(str)) {
232                 xenbus_transaction_end(xbt, 1);
233                 return;
234         }
235
236         for (handler = &handlers[0]; handler->command; handler++) {
237                 if (strcmp(str, handler->command) == 0)
238                         break;
239         }
240
241         /* Only acknowledge commands which we are prepared to handle. */
242         if (handler->cb)
243                 xenbus_write(xbt, "control", "shutdown", "");
244
245         err = xenbus_transaction_end(xbt, 0);
246         if (err == -EAGAIN) {
247                 kfree(str);
248                 goto again;
249         }
250
251         if (handler->cb) {
252                 handler->cb();
253         } else {
254                 pr_info("Ignoring shutdown request: %s\n", str);
255                 shutting_down = SHUTDOWN_INVALID;
256         }
257
258         kfree(str);
259 }
260
261 #ifdef CONFIG_MAGIC_SYSRQ
262 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
263                           unsigned int len)
264 {
265         char sysrq_key = '\0';
266         struct xenbus_transaction xbt;
267         int err;
268
269  again:
270         err = xenbus_transaction_start(&xbt);
271         if (err)
272                 return;
273         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
274                 pr_err("Unable to read sysrq code in control/sysrq\n");
275                 xenbus_transaction_end(xbt, 1);
276                 return;
277         }
278
279         if (sysrq_key != '\0')
280                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
281
282         err = xenbus_transaction_end(xbt, 0);
283         if (err == -EAGAIN)
284                 goto again;
285
286         if (sysrq_key != '\0')
287                 handle_sysrq(sysrq_key);
288 }
289
290 static struct xenbus_watch sysrq_watch = {
291         .node = "control/sysrq",
292         .callback = sysrq_handler
293 };
294 #endif
295
296 static struct xenbus_watch shutdown_watch = {
297         .node = "control/shutdown",
298         .callback = shutdown_handler
299 };
300
301 static struct notifier_block xen_reboot_nb = {
302         .notifier_call = poweroff_nb,
303 };
304
305 static int setup_shutdown_watcher(void)
306 {
307         int err;
308
309         err = register_xenbus_watch(&shutdown_watch);
310         if (err) {
311                 pr_err("Failed to set shutdown watcher\n");
312                 return err;
313         }
314
315
316 #ifdef CONFIG_MAGIC_SYSRQ
317         err = register_xenbus_watch(&sysrq_watch);
318         if (err) {
319                 pr_err("Failed to set sysrq watcher\n");
320                 return err;
321         }
322 #endif
323
324         return 0;
325 }
326
327 static int shutdown_event(struct notifier_block *notifier,
328                           unsigned long event,
329                           void *data)
330 {
331         setup_shutdown_watcher();
332         return NOTIFY_DONE;
333 }
334
335 int xen_setup_shutdown_event(void)
336 {
337         static struct notifier_block xenstore_notifier = {
338                 .notifier_call = shutdown_event
339         };
340
341         if (!xen_domain())
342                 return -ENODEV;
343         register_xenstore_notifier(&xenstore_notifier);
344         register_reboot_notifier(&xen_reboot_nb);
345
346         return 0;
347 }
348 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
349
350 subsys_initcall(xen_setup_shutdown_event);