dma : EG20T PCH: Fix miss-setting DMA descriptor
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / xen / manage.c
blobef9c7db52077c6d58c0d5f036be0a03bd771dffa
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>
12 #include <xen/xen.h>
13 #include <xen/xenbus.h>
14 #include <xen/grant_table.h>
15 #include <xen/events.h>
16 #include <xen/hvc-console.h>
17 #include <xen/xen-ops.h>
19 #include <asm/xen/hypercall.h>
20 #include <asm/xen/page.h>
21 #include <asm/xen/hypervisor.h>
23 enum shutdown_state {
24 SHUTDOWN_INVALID = -1,
25 SHUTDOWN_POWEROFF = 0,
26 SHUTDOWN_SUSPEND = 2,
27 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
28 report a crash, not be instructed to crash!
29 HALT is the same as POWEROFF, as far as we're concerned. The tools use
30 the distinction when we return the reason code to them. */
31 SHUTDOWN_HALT = 4,
34 /* Ignore multiple shutdown requests. */
35 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
37 #ifdef CONFIG_PM_SLEEP
38 static int xen_hvm_suspend(void *data)
40 struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
41 int *cancelled = data;
43 BUG_ON(!irqs_disabled());
45 *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
47 xen_hvm_post_suspend(*cancelled);
48 gnttab_resume();
50 if (!*cancelled) {
51 xen_irq_resume();
52 xen_timer_resume();
55 return 0;
58 static int xen_suspend(void *data)
60 int err;
61 int *cancelled = data;
63 BUG_ON(!irqs_disabled());
65 err = sysdev_suspend(PMSG_SUSPEND);
66 if (err) {
67 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
68 err);
69 return err;
72 xen_mm_pin_all();
73 gnttab_suspend();
74 xen_pre_suspend();
77 * This hypercall returns 1 if suspend was cancelled
78 * or the domain was merely checkpointed, and 0 if it
79 * is resuming in a new domain.
81 *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
83 xen_post_suspend(*cancelled);
84 gnttab_resume();
85 xen_mm_unpin_all();
87 if (!*cancelled) {
88 xen_irq_resume();
89 xen_console_resume();
90 xen_timer_resume();
93 sysdev_resume();
95 return 0;
98 static void do_suspend(void)
100 int err;
101 int cancelled = 1;
103 shutting_down = SHUTDOWN_SUSPEND;
105 #ifdef CONFIG_PREEMPT
106 /* If the kernel is preemptible, we need to freeze all the processes
107 to prevent them from being in the middle of a pagetable update
108 during suspend. */
109 err = freeze_processes();
110 if (err) {
111 printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
112 goto out;
114 #endif
116 err = dpm_suspend_start(PMSG_SUSPEND);
117 if (err) {
118 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
119 goto out_thaw;
122 printk(KERN_DEBUG "suspending xenstore...\n");
123 xs_suspend();
125 err = dpm_suspend_noirq(PMSG_SUSPEND);
126 if (err) {
127 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
128 goto out_resume;
131 if (xen_hvm_domain())
132 err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
133 else
134 err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
136 dpm_resume_noirq(PMSG_RESUME);
138 if (err) {
139 printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
140 cancelled = 1;
143 out_resume:
144 if (!cancelled) {
145 xen_arch_resume();
146 xs_resume();
147 } else
148 xs_suspend_cancel();
150 dpm_resume_end(PMSG_RESUME);
152 /* Make sure timer events get retriggered on all CPUs */
153 clock_was_set();
155 out_thaw:
156 #ifdef CONFIG_PREEMPT
157 thaw_processes();
158 out:
159 #endif
160 shutting_down = SHUTDOWN_INVALID;
162 #endif /* CONFIG_PM_SLEEP */
164 static void shutdown_handler(struct xenbus_watch *watch,
165 const char **vec, unsigned int len)
167 char *str;
168 struct xenbus_transaction xbt;
169 int err;
171 if (shutting_down != SHUTDOWN_INVALID)
172 return;
174 again:
175 err = xenbus_transaction_start(&xbt);
176 if (err)
177 return;
179 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
180 /* Ignore read errors and empty reads. */
181 if (XENBUS_IS_ERR_READ(str)) {
182 xenbus_transaction_end(xbt, 1);
183 return;
186 xenbus_write(xbt, "control", "shutdown", "");
188 err = xenbus_transaction_end(xbt, 0);
189 if (err == -EAGAIN) {
190 kfree(str);
191 goto again;
194 if (strcmp(str, "poweroff") == 0 ||
195 strcmp(str, "halt") == 0) {
196 shutting_down = SHUTDOWN_POWEROFF;
197 orderly_poweroff(false);
198 } else if (strcmp(str, "reboot") == 0) {
199 shutting_down = SHUTDOWN_POWEROFF; /* ? */
200 ctrl_alt_del();
201 #ifdef CONFIG_PM_SLEEP
202 } else if (strcmp(str, "suspend") == 0) {
203 do_suspend();
204 #endif
205 } else {
206 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
207 shutting_down = SHUTDOWN_INVALID;
210 kfree(str);
213 #ifdef CONFIG_MAGIC_SYSRQ
214 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
215 unsigned int len)
217 char sysrq_key = '\0';
218 struct xenbus_transaction xbt;
219 int err;
221 again:
222 err = xenbus_transaction_start(&xbt);
223 if (err)
224 return;
225 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
226 printk(KERN_ERR "Unable to read sysrq code in "
227 "control/sysrq\n");
228 xenbus_transaction_end(xbt, 1);
229 return;
232 if (sysrq_key != '\0')
233 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
235 err = xenbus_transaction_end(xbt, 0);
236 if (err == -EAGAIN)
237 goto again;
239 if (sysrq_key != '\0')
240 handle_sysrq(sysrq_key);
243 static struct xenbus_watch sysrq_watch = {
244 .node = "control/sysrq",
245 .callback = sysrq_handler
247 #endif
249 static struct xenbus_watch shutdown_watch = {
250 .node = "control/shutdown",
251 .callback = shutdown_handler
254 static int setup_shutdown_watcher(void)
256 int err;
258 err = register_xenbus_watch(&shutdown_watch);
259 if (err) {
260 printk(KERN_ERR "Failed to set shutdown watcher\n");
261 return err;
264 #ifdef CONFIG_MAGIC_SYSRQ
265 err = register_xenbus_watch(&sysrq_watch);
266 if (err) {
267 printk(KERN_ERR "Failed to set sysrq watcher\n");
268 return err;
270 #endif
272 return 0;
275 static int shutdown_event(struct notifier_block *notifier,
276 unsigned long event,
277 void *data)
279 setup_shutdown_watcher();
280 return NOTIFY_DONE;
283 static int __init __setup_shutdown_event(void)
285 /* Delay initialization in the PV on HVM case */
286 if (xen_hvm_domain())
287 return 0;
289 if (!xen_pv_domain())
290 return -ENODEV;
292 return xen_setup_shutdown_event();
295 int xen_setup_shutdown_event(void)
297 static struct notifier_block xenstore_notifier = {
298 .notifier_call = shutdown_event
300 register_xenstore_notifier(&xenstore_notifier);
302 return 0;
304 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
306 subsys_initcall(__setup_shutdown_event);