WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] xen suspend: Fix suspend-via-evtchn r

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] xen suspend: Fix suspend-via-evtchn reentrancy.
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 31 Jul 2008 15:30:09 -0700
Delivery-date: Thu, 31 Jul 2008 15:29:54 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1217514834 -3600
# Node ID 2866e6af503ea0b33e1c1fb2340ab8ed81925e97
# Parent  44e3ace9a1f154941f7ccfb97cb75a8ab01ac3d1
xen suspend: Fix suspend-via-evtchn reentrancy.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 drivers/xen/core/machine_reboot.c |    9 +----
 drivers/xen/core/reboot.c         |   63 ++++++++++++++++++++++++++------------
 2 files changed, 47 insertions(+), 25 deletions(-)

diff -r 44e3ace9a1f1 -r 2866e6af503e drivers/xen/core/machine_reboot.c
--- a/drivers/xen/core/machine_reboot.c Thu Jul 31 09:46:58 2008 +0100
+++ b/drivers/xen/core/machine_reboot.c Thu Jul 31 15:33:54 2008 +0100
@@ -26,8 +26,6 @@ void (*pm_power_off)(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-int setup_suspend_evtchn(void);
-
 void machine_emergency_restart(void)
 {
        /* We really want to get pending console data out before we die. */
@@ -133,7 +131,7 @@ static void post_suspend(int suspend_can
 
 struct suspend {
        int fast_suspend;
-       void (*resume_notifier)(void);
+       void (*resume_notifier)(int);
 };
 
 static int take_machine_down(void *_suspend)
@@ -175,7 +173,7 @@ static int take_machine_down(void *_susp
         */
        suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
 
-       suspend->resume_notifier();
+       suspend->resume_notifier(suspend_cancelled);
        post_suspend(suspend_cancelled);
        gnttab_resume();
        if (!suspend_cancelled) {
@@ -204,7 +202,7 @@ static int take_machine_down(void *_susp
        return suspend_cancelled;
 }
 
-int __xen_suspend(int fast_suspend, void (*resume_notifier)(void))
+int __xen_suspend(int fast_suspend, void (*resume_notifier)(int))
 {
        int err, suspend_cancelled;
        struct suspend suspend;
@@ -243,7 +241,6 @@ int __xen_suspend(int fast_suspend, void
        if (!suspend_cancelled) {
                xencons_resume();
                xenbus_resume();
-               setup_suspend_evtchn();
        } else {
                xenbus_suspend_cancel();
        }
diff -r 44e3ace9a1f1 -r 2866e6af503e drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c Thu Jul 31 09:46:58 2008 +0100
+++ b/drivers/xen/core/reboot.c Thu Jul 31 15:33:54 2008 +0100
@@ -27,13 +27,18 @@ MODULE_LICENSE("Dual BSD/GPL");
 /* Ignore multiple shutdown requests. */
 static int shutting_down = SHUTDOWN_INVALID;
 
+/* Was last suspend request cancelled? */
+static int suspend_cancelled;
+
 /* Can we leave APs online when we suspend? */
 static int fast_suspend;
 
 static void __shutdown_handler(void *unused);
 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
 
-int __xen_suspend(int fast_suspend, void (*resume_notifier)(void));
+static int setup_suspend_evtchn(void);
+
+int __xen_suspend(int fast_suspend, void (*resume_notifier)(int));
 
 static int shutdown_process(void *__unused)
 {
@@ -62,10 +67,11 @@ static int shutdown_process(void *__unus
        return 0;
 }
 
-static void xen_resume_notifier(void)
+static void xen_resume_notifier(int _suspend_cancelled)
 {
        int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
        BUG_ON(old_state != SHUTDOWN_SUSPEND);
+       suspend_cancelled = _suspend_cancelled;
 }
 
 static int xen_suspend(void *__unused)
@@ -85,6 +91,8 @@ static int xen_suspend(void *__unused)
                        printk(KERN_ERR "Xen suspend failed (%d)\n", err);
                        goto fail;
                }
+               if (!suspend_cancelled)
+                       setup_suspend_evtchn();
                old_state = cmpxchg(
                        &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID);
        } while (old_state == SHUTDOWN_SUSPEND);
@@ -108,6 +116,31 @@ static int xen_suspend(void *__unused)
        return 0;
 }
 
+static void switch_shutdown_state(int new_state)
+{
+       int prev_state, old_state = SHUTDOWN_INVALID;
+
+       /* We only drive shutdown_state into an active state. */
+       if (new_state == SHUTDOWN_INVALID)
+               return;
+
+       do {
+               /* We drop this transition if already in an active state. */
+               if ((old_state != SHUTDOWN_INVALID) &&
+                   (old_state != SHUTDOWN_RESUMING))
+                       return;
+               /* Attempt to transition. */
+               prev_state = old_state;
+               old_state = cmpxchg(&shutting_down, old_state, new_state);
+       } while (old_state != prev_state);
+
+       /* Either we kick off the work, or we leave it to xen_suspend(). */
+       if (old_state == SHUTDOWN_INVALID)
+               schedule_work(&shutdown_work);
+       else
+               BUG_ON(old_state != SHUTDOWN_RESUMING);
+}
+
 static void __shutdown_handler(void *unused)
 {
        int err;
@@ -129,7 +162,7 @@ static void shutdown_handler(struct xenb
        extern void ctrl_alt_del(void);
        char *str;
        struct xenbus_transaction xbt;
-       int err, old_state, new_state = SHUTDOWN_INVALID;
+       int err, new_state = SHUTDOWN_INVALID;
 
        if ((shutting_down != SHUTDOWN_INVALID) &&
            (shutting_down != SHUTDOWN_RESUMING))
@@ -166,13 +199,7 @@ static void shutdown_handler(struct xenb
        else
                printk("Ignoring shutdown request: %s\n", str);
 
-       if (new_state != SHUTDOWN_INVALID) {
-               old_state = xchg(&shutting_down, new_state);
-               if (old_state == SHUTDOWN_INVALID)
-                       schedule_work(&shutdown_work);
-               else
-                       BUG_ON(old_state != SHUTDOWN_RESUMING);
-       }
+       switch_shutdown_state(new_state);
 
        kfree(str);
 }
@@ -220,26 +247,24 @@ static struct xenbus_watch sysrq_watch =
 
 static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
 {
-       shutting_down = SHUTDOWN_SUSPEND;
-       schedule_work(&shutdown_work);
-
+       switch_shutdown_state(SHUTDOWN_SUSPEND);
        return IRQ_HANDLED;
 }
 
-int setup_suspend_evtchn(void)
-{
-       static int irq = -1;
+static int setup_suspend_evtchn(void)
+{
+       static int irq;
        int port;
-       char portstr[5]; /* 1024 max */
+       char portstr[16];
 
        if (irq > 0)
                unbind_from_irqhandler(irq, NULL);
 
        irq = bind_listening_port_to_irqhandler(0, suspend_int, 0, "suspend",
                                                NULL);
-       if (irq <= 0) {
+       if (irq <= 0)
                return -1;
-       }
+
        port = irq_to_evtchn_port(irq);
        printk(KERN_INFO "suspend: event channel %d\n", port);
        sprintf(portstr, "%d", port);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] xen suspend: Fix suspend-via-evtchn reentrancy., Xen patchbot-linux-2.6.18-xen <=