# HG changeset patch
# User Brendan Cully <brendan@xxxxxxxxx>
# Date 1215120859 25200
# Node ID af2845b0a746f9be5d7d087951ef99c0ca4a1687
# Parent 88e01408ec0da0c406fde22a0003bd870144f180
Set up an event channel to accept suspend requests.
This is much faster than going through xenstore.
Signed-off-by: Brendan Cullly <brendan@xxxxxxxxx>
diff --git a/drivers/xen/core/machine_reboot.c
b/drivers/xen/core/machine_reboot.c
--- a/drivers/xen/core/machine_reboot.c
+++ b/drivers/xen/core/machine_reboot.c
@@ -25,6 +25,8 @@
*/
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
+
+int setup_suspend_evtchn(void);
void machine_emergency_restart(void)
{
@@ -241,6 +243,7 @@
if (!suspend_cancelled) {
xencons_resume();
xenbus_resume();
+ setup_suspend_evtchn();
} else {
xenbus_suspend_cancel();
}
diff --git a/drivers/xen/core/reboot.c b/drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c
+++ b/drivers/xen/core/reboot.c
@@ -7,6 +7,7 @@
#include <linux/sysrq.h>
#include <asm/hypervisor.h>
#include <xen/xenbus.h>
+#include <xen/evtchn.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -217,6 +218,36 @@
.callback = sysrq_handler
};
+static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
+{
+ shutting_down = SHUTDOWN_SUSPEND;
+ schedule_work(&shutdown_work);
+
+ return IRQ_HANDLED;
+}
+
+int setup_suspend_evtchn(void)
+{
+ static int irq = -1;
+ int port;
+ char portstr[5]; /* 1024 max */
+
+ if (irq > 0)
+ unbind_from_irqhandler(irq, NULL);
+
+ irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
+ NULL);
+ if (irq <= 0) {
+ return -1;
+ }
+ port = irq_to_evtchn_port(irq);
+ printk(KERN_INFO "suspend: event channel %d\n", port);
+ sprintf(portstr, "%d", port);
+ xenbus_write(XBT_NIL, "device/suspend", "event-channel", portstr);
+
+ return 0;
+}
+
static int setup_shutdown_watcher(void)
{
int err;
@@ -234,6 +265,13 @@
err = register_xenbus_watch(&sysrq_watch);
if (err) {
printk(KERN_ERR "Failed to set sysrq watcher\n");
+ return err;
+ }
+
+ /* suspend event channel */
+ err = setup_suspend_evtchn();
+ if (err) {
+ printk(KERN_ERR "Failed to register suspend event channel\n");
return err;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|