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