ia64/linux-2.6.18-xen.hg

changeset 591:cdadea74443c

Set up an event channel to accept suspend requests.
This is much faster than going through xenstore.

Signed-off-by: Brendan Cullly <brendan@cs.ubc.ca>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jul 04 11:59:59 2008 +0100 (2008-07-04)
parents c4134d1a3e3f
children a2e385815f36
files drivers/xen/core/machine_reboot.c drivers/xen/core/reboot.c
line diff
     1.1 --- a/drivers/xen/core/machine_reboot.c	Thu Jul 03 13:40:02 2008 +0100
     1.2 +++ b/drivers/xen/core/machine_reboot.c	Fri Jul 04 11:59:59 2008 +0100
     1.3 @@ -26,6 +26,8 @@
     1.4  void (*pm_power_off)(void);
     1.5  EXPORT_SYMBOL(pm_power_off);
     1.6  
     1.7 +int setup_suspend_evtchn(void);
     1.8 +
     1.9  void machine_emergency_restart(void)
    1.10  {
    1.11  	/* We really want to get pending console data out before we die. */
    1.12 @@ -241,6 +243,7 @@ int __xen_suspend(int fast_suspend, void
    1.13  	if (!suspend_cancelled) {
    1.14  		xencons_resume();
    1.15  		xenbus_resume();
    1.16 +		setup_suspend_evtchn();
    1.17  	} else {
    1.18  		xenbus_suspend_cancel();
    1.19  	}
     2.1 --- a/drivers/xen/core/reboot.c	Thu Jul 03 13:40:02 2008 +0100
     2.2 +++ b/drivers/xen/core/reboot.c	Fri Jul 04 11:59:59 2008 +0100
     2.3 @@ -7,6 +7,7 @@
     2.4  #include <linux/sysrq.h>
     2.5  #include <asm/hypervisor.h>
     2.6  #include <xen/xenbus.h>
     2.7 +#include <xen/evtchn.h>
     2.8  #include <linux/kmod.h>
     2.9  #include <linux/slab.h>
    2.10  #include <linux/workqueue.h>
    2.11 @@ -217,6 +218,36 @@ static struct xenbus_watch sysrq_watch =
    2.12  	.callback = sysrq_handler
    2.13  };
    2.14  
    2.15 +static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
    2.16 +{
    2.17 +	shutting_down = SHUTDOWN_SUSPEND;
    2.18 +	schedule_work(&shutdown_work);
    2.19 +
    2.20 +	return IRQ_HANDLED;
    2.21 +}
    2.22 +
    2.23 +int setup_suspend_evtchn(void)
    2.24 +{
    2.25 +	static int irq = -1;
    2.26 +	int port;
    2.27 +	char portstr[5]; /* 1024 max */
    2.28 +
    2.29 +	if (irq > 0)
    2.30 +		unbind_from_irqhandler(irq, NULL);
    2.31 +
    2.32 +	irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
    2.33 +						NULL);
    2.34 +	if (irq <= 0) {
    2.35 +		return -1;
    2.36 +	}
    2.37 +	port = irq_to_evtchn_port(irq);
    2.38 +	printk(KERN_INFO "suspend: event channel %d\n", port);
    2.39 +	sprintf(portstr, "%d", port);
    2.40 +	xenbus_write(XBT_NIL, "device/suspend", "event-channel", portstr);
    2.41 +
    2.42 +	return 0;
    2.43 +}
    2.44 +
    2.45  static int setup_shutdown_watcher(void)
    2.46  {
    2.47  	int err;
    2.48 @@ -237,6 +268,13 @@ static int setup_shutdown_watcher(void)
    2.49  		return err;
    2.50  	}
    2.51  
    2.52 +	/* suspend event channel */
    2.53 +	err = setup_suspend_evtchn();
    2.54 +	if (err) {
    2.55 +		printk(KERN_ERR "Failed to register suspend event channel\n");
    2.56 +		return err;
    2.57 +	}
    2.58 +
    2.59  	return 0;
    2.60  }
    2.61