gpio: make gpiod_direction_output take a logical value
[platform/adaptation/renesas_rcar/renesas_kernel.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         unsigned long arg; /* extra hypercall argument */
45         void (*pre)(void);
46         void (*post)(int cancelled);
47 };
48
49 #ifdef CONFIG_HIBERNATE_CALLBACKS
50 static void xen_hvm_post_suspend(int cancelled)
51 {
52         xen_arch_hvm_post_suspend(cancelled);
53         gnttab_resume();
54 }
55
56 static void xen_pre_suspend(void)
57 {
58         xen_mm_pin_all();
59         gnttab_suspend();
60         xen_arch_pre_suspend();
61 }
62
63 static void xen_post_suspend(int cancelled)
64 {
65         xen_arch_post_suspend(cancelled);
66         gnttab_resume();
67         xen_mm_unpin_all();
68 }
69
70 static int xen_suspend(void *data)
71 {
72         struct suspend_info *si = data;
73         int err;
74
75         BUG_ON(!irqs_disabled());
76
77         err = syscore_suspend();
78         if (err) {
79                 pr_err("%s: system core suspend failed: %d\n", __func__, err);
80                 return err;
81         }
82
83         if (si->pre)
84                 si->pre();
85
86         /*
87          * This hypercall returns 1 if suspend was cancelled
88          * or the domain was merely checkpointed, and 0 if it
89          * is resuming in a new domain.
90          */
91         si->cancelled = HYPERVISOR_suspend(si->arg);
92
93         if (si->post)
94                 si->post(si->cancelled);
95
96         if (!si->cancelled) {
97                 xen_irq_resume();
98                 xen_console_resume();
99                 xen_timer_resume();
100         }
101
102         syscore_resume();
103
104         return 0;
105 }
106
107 static void do_suspend(void)
108 {
109         int err;
110         struct suspend_info si;
111
112         shutting_down = SHUTDOWN_SUSPEND;
113
114         err = freeze_processes();
115         if (err) {
116                 pr_err("%s: freeze failed %d\n", __func__, err);
117                 goto out;
118         }
119
120         err = dpm_suspend_start(PMSG_FREEZE);
121         if (err) {
122                 pr_err("%s: dpm_suspend_start %d\n", __func__, err);
123                 goto out_thaw;
124         }
125
126         printk(KERN_DEBUG "suspending xenstore...\n");
127         xs_suspend();
128
129         err = dpm_suspend_end(PMSG_FREEZE);
130         if (err) {
131                 pr_err("dpm_suspend_end failed: %d\n", err);
132                 si.cancelled = 0;
133                 goto out_resume;
134         }
135
136         si.cancelled = 1;
137
138         if (xen_hvm_domain()) {
139                 si.arg = 0UL;
140                 si.pre = NULL;
141                 si.post = &xen_hvm_post_suspend;
142         } else {
143                 si.arg = virt_to_mfn(xen_start_info);
144                 si.pre = &xen_pre_suspend;
145                 si.post = &xen_post_suspend;
146         }
147
148         err = stop_machine(xen_suspend, &si, cpumask_of(0));
149
150         dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
151
152         if (err) {
153                 pr_err("failed to start xen_suspend: %d\n", err);
154                 si.cancelled = 1;
155         }
156
157 out_resume:
158         if (!si.cancelled) {
159                 xen_arch_resume();
160                 xs_resume();
161         } else
162                 xs_suspend_cancel();
163
164         dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
165
166 out_thaw:
167         thaw_processes();
168 out:
169         shutting_down = SHUTDOWN_INVALID;
170 }
171 #endif  /* CONFIG_HIBERNATE_CALLBACKS */
172
173 struct shutdown_handler {
174         const char *command;
175         void (*cb)(void);
176 };
177
178 static void do_poweroff(void)
179 {
180         shutting_down = SHUTDOWN_POWEROFF;
181         orderly_poweroff(false);
182 }
183
184 static void do_reboot(void)
185 {
186         shutting_down = SHUTDOWN_POWEROFF; /* ? */
187         ctrl_alt_del();
188 }
189
190 static void shutdown_handler(struct xenbus_watch *watch,
191                              const char **vec, unsigned int len)
192 {
193         char *str;
194         struct xenbus_transaction xbt;
195         int err;
196         static struct shutdown_handler handlers[] = {
197                 { "poweroff",   do_poweroff },
198                 { "halt",       do_poweroff },
199                 { "reboot",     do_reboot   },
200 #ifdef CONFIG_HIBERNATE_CALLBACKS
201                 { "suspend",    do_suspend  },
202 #endif
203                 {NULL, NULL},
204         };
205         static struct shutdown_handler *handler;
206
207         if (shutting_down != SHUTDOWN_INVALID)
208                 return;
209
210  again:
211         err = xenbus_transaction_start(&xbt);
212         if (err)
213                 return;
214
215         str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
216         /* Ignore read errors and empty reads. */
217         if (XENBUS_IS_ERR_READ(str)) {
218                 xenbus_transaction_end(xbt, 1);
219                 return;
220         }
221
222         for (handler = &handlers[0]; handler->command; handler++) {
223                 if (strcmp(str, handler->command) == 0)
224                         break;
225         }
226
227         /* Only acknowledge commands which we are prepared to handle. */
228         if (handler->cb)
229                 xenbus_write(xbt, "control", "shutdown", "");
230
231         err = xenbus_transaction_end(xbt, 0);
232         if (err == -EAGAIN) {
233                 kfree(str);
234                 goto again;
235         }
236
237         if (handler->cb) {
238                 handler->cb();
239         } else {
240                 pr_info("Ignoring shutdown request: %s\n", str);
241                 shutting_down = SHUTDOWN_INVALID;
242         }
243
244         kfree(str);
245 }
246
247 #ifdef CONFIG_MAGIC_SYSRQ
248 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
249                           unsigned int len)
250 {
251         char sysrq_key = '\0';
252         struct xenbus_transaction xbt;
253         int err;
254
255  again:
256         err = xenbus_transaction_start(&xbt);
257         if (err)
258                 return;
259         if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
260                 pr_err("Unable to read sysrq code in control/sysrq\n");
261                 xenbus_transaction_end(xbt, 1);
262                 return;
263         }
264
265         if (sysrq_key != '\0')
266                 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
267
268         err = xenbus_transaction_end(xbt, 0);
269         if (err == -EAGAIN)
270                 goto again;
271
272         if (sysrq_key != '\0')
273                 handle_sysrq(sysrq_key);
274 }
275
276 static struct xenbus_watch sysrq_watch = {
277         .node = "control/sysrq",
278         .callback = sysrq_handler
279 };
280 #endif
281
282 static struct xenbus_watch shutdown_watch = {
283         .node = "control/shutdown",
284         .callback = shutdown_handler
285 };
286
287 static int setup_shutdown_watcher(void)
288 {
289         int err;
290
291         err = register_xenbus_watch(&shutdown_watch);
292         if (err) {
293                 pr_err("Failed to set shutdown watcher\n");
294                 return err;
295         }
296
297 #ifdef CONFIG_MAGIC_SYSRQ
298         err = register_xenbus_watch(&sysrq_watch);
299         if (err) {
300                 pr_err("Failed to set sysrq watcher\n");
301                 return err;
302         }
303 #endif
304
305         return 0;
306 }
307
308 static int shutdown_event(struct notifier_block *notifier,
309                           unsigned long event,
310                           void *data)
311 {
312         setup_shutdown_watcher();
313         return NOTIFY_DONE;
314 }
315
316 int xen_setup_shutdown_event(void)
317 {
318         static struct notifier_block xenstore_notifier = {
319                 .notifier_call = shutdown_event
320         };
321
322         if (!xen_domain())
323                 return -ENODEV;
324         register_xenstore_notifier(&xenstore_notifier);
325
326         return 0;
327 }
328 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
329
330 subsys_initcall(xen_setup_shutdown_event);