include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / xen / manage.c
1 /*
2 * Handle extern requests for shutdown, reboot and sysrq
3 */
4 #include <linux/kernel.h>
5 #include <linux/err.h>
6 #include <linux/slab.h>
7 #include <linux/reboot.h>
8 #include <linux/sysrq.h>
9 #include <linux/stop_machine.h>
10 #include <linux/freezer.h>
11
12 #include <xen/xenbus.h>
13 #include <xen/grant_table.h>
14 #include <xen/events.h>
15 #include <xen/hvc-console.h>
16 #include <xen/xen-ops.h>
17
18 #include <asm/xen/hypercall.h>
19 #include <asm/xen/page.h>
20
21 enum shutdown_state {
22 SHUTDOWN_INVALID = -1,
23 SHUTDOWN_POWEROFF = 0,
24 SHUTDOWN_SUSPEND = 2,
25 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
26 report a crash, not be instructed to crash!
27 HALT is the same as POWEROFF, as far as we're concerned. The tools use
28 the distinction when we return the reason code to them. */
29 SHUTDOWN_HALT = 4,
30 };
31
32 /* Ignore multiple shutdown requests. */
33 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
34
35 #ifdef CONFIG_PM_SLEEP
36 static int xen_suspend(void *data)
37 {
38 int *cancelled = data;
39 int err;
40
41 BUG_ON(!irqs_disabled());
42
43 err = sysdev_suspend(PMSG_SUSPEND);
44 if (err) {
45 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
46 err);
47 return err;
48 }
49
50 xen_mm_pin_all();
51 gnttab_suspend();
52 xen_pre_suspend();
53
54 /*
55 * This hypercall returns 1 if suspend was cancelled
56 * or the domain was merely checkpointed, and 0 if it
57 * is resuming in a new domain.
58 */
59 *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
60
61 xen_post_suspend(*cancelled);
62 gnttab_resume();
63 xen_mm_unpin_all();
64
65 if (!*cancelled) {
66 xen_irq_resume();
67 xen_console_resume();
68 xen_timer_resume();
69 }
70
71 sysdev_resume();
72
73 return 0;
74 }
75
76 static void do_suspend(void)
77 {
78 int err;
79 int cancelled = 1;
80
81 shutting_down = SHUTDOWN_SUSPEND;
82
83 err = stop_machine_create();
84 if (err) {
85 printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err);
86 goto out;
87 }
88
89 #ifdef CONFIG_PREEMPT
90 /* If the kernel is preemptible, we need to freeze all the processes
91 to prevent them from being in the middle of a pagetable update
92 during suspend. */
93 err = freeze_processes();
94 if (err) {
95 printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
96 goto out_destroy_sm;
97 }
98 #endif
99
100 err = dpm_suspend_start(PMSG_SUSPEND);
101 if (err) {
102 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
103 goto out_thaw;
104 }
105
106 printk(KERN_DEBUG "suspending xenstore...\n");
107 xs_suspend();
108
109 err = dpm_suspend_noirq(PMSG_SUSPEND);
110 if (err) {
111 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
112 goto out_resume;
113 }
114
115 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
116
117 dpm_resume_noirq(PMSG_RESUME);
118
119 if (err) {
120 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
121 cancelled = 1;
122 }
123
124 out_resume:
125 if (!cancelled) {
126 xen_arch_resume();
127 xs_resume();
128 } else
129 xs_suspend_cancel();
130
131 dpm_resume_end(PMSG_RESUME);
132
133 /* Make sure timer events get retriggered on all CPUs */
134 clock_was_set();
135
136 out_thaw:
137 #ifdef CONFIG_PREEMPT
138 thaw_processes();
139
140 out_destroy_sm:
141 #endif
142 stop_machine_destroy();
143
144 out:
145 shutting_down = SHUTDOWN_INVALID;
146 }
147 #endif /* CONFIG_PM_SLEEP */
148
149 static void shutdown_handler(struct xenbus_watch *watch,
150 const char **vec, unsigned int len)
151 {
152 char *str;
153 struct xenbus_transaction xbt;
154 int err;
155
156 if (shutting_down != SHUTDOWN_INVALID)
157 return;
158
159 again:
160 err = xenbus_transaction_start(&xbt);
161 if (err)
162 return;
163
164 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
165 /* Ignore read errors and empty reads. */
166 if (XENBUS_IS_ERR_READ(str)) {
167 xenbus_transaction_end(xbt, 1);
168 return;
169 }
170
171 xenbus_write(xbt, "control", "shutdown", "");
172
173 err = xenbus_transaction_end(xbt, 0);
174 if (err == -EAGAIN) {
175 kfree(str);
176 goto again;
177 }
178
179 if (strcmp(str, "poweroff") == 0 ||
180 strcmp(str, "halt") == 0) {
181 shutting_down = SHUTDOWN_POWEROFF;
182 orderly_poweroff(false);
183 } else if (strcmp(str, "reboot") == 0) {
184 shutting_down = SHUTDOWN_POWEROFF; /* ? */
185 ctrl_alt_del();
186 #ifdef CONFIG_PM_SLEEP
187 } else if (strcmp(str, "suspend") == 0) {
188 do_suspend();
189 #endif
190 } else {
191 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
192 shutting_down = SHUTDOWN_INVALID;
193 }
194
195 kfree(str);
196 }
197
198 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
199 unsigned int len)
200 {
201 char sysrq_key = '\0';
202 struct xenbus_transaction xbt;
203 int err;
204
205 again:
206 err = xenbus_transaction_start(&xbt);
207 if (err)
208 return;
209 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
210 printk(KERN_ERR "Unable to read sysrq code in "
211 "control/sysrq\n");
212 xenbus_transaction_end(xbt, 1);
213 return;
214 }
215
216 if (sysrq_key != '\0')
217 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
218
219 err = xenbus_transaction_end(xbt, 0);
220 if (err == -EAGAIN)
221 goto again;
222
223 if (sysrq_key != '\0')
224 handle_sysrq(sysrq_key, NULL);
225 }
226
227 static struct xenbus_watch shutdown_watch = {
228 .node = "control/shutdown",
229 .callback = shutdown_handler
230 };
231
232 static struct xenbus_watch sysrq_watch = {
233 .node = "control/sysrq",
234 .callback = sysrq_handler
235 };
236
237 static int setup_shutdown_watcher(void)
238 {
239 int err;
240
241 err = register_xenbus_watch(&shutdown_watch);
242 if (err) {
243 printk(KERN_ERR "Failed to set shutdown watcher\n");
244 return err;
245 }
246
247 err = register_xenbus_watch(&sysrq_watch);
248 if (err) {
249 printk(KERN_ERR "Failed to set sysrq watcher\n");
250 return err;
251 }
252
253 return 0;
254 }
255
256 static int shutdown_event(struct notifier_block *notifier,
257 unsigned long event,
258 void *data)
259 {
260 setup_shutdown_watcher();
261 return NOTIFY_DONE;
262 }
263
264 static int __init setup_shutdown_event(void)
265 {
266 static struct notifier_block xenstore_notifier = {
267 .notifier_call = shutdown_event
268 };
269 register_xenstore_notifier(&xenstore_notifier);
270
271 return 0;
272 }
273
274 subsys_initcall(setup_shutdown_event);