source: trunk/packages/xen-3.1/xen-3.1/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 1.8 KB
Line 
1#include <linux/config.h>
2#include <linux/stop_machine.h>
3#include <xen/evtchn.h>
4#include <xen/gnttab.h>
5#include <xen/xenbus.h>
6#include "platform-pci.h"
7#include <asm/hypervisor.h>
8
9struct ap_suspend_info {
10        int      do_spin;
11        atomic_t nr_spinning;
12};
13
14/*
15 * Spinning prevents, for example, APs touching grant table entries while
16 * the shared grant table is not mapped into the address space imemdiately
17 * after resume.
18 */
19static void ap_suspend(void *_info)
20{
21        struct ap_suspend_info *info = _info;
22
23        BUG_ON(!irqs_disabled());
24
25        atomic_inc(&info->nr_spinning);
26        mb();
27
28        while (info->do_spin) {
29                cpu_relax();
30                HYPERVISOR_yield();
31        }
32
33        mb();
34        atomic_dec(&info->nr_spinning);
35}
36
37static int bp_suspend(void)
38{
39        int suspend_cancelled;
40
41        BUG_ON(!irqs_disabled());
42
43        suspend_cancelled = HYPERVISOR_shutdown(SHUTDOWN_suspend);
44
45        if (!suspend_cancelled) {
46                platform_pci_resume();
47                gnttab_resume();
48                irq_resume();
49        }
50
51        return suspend_cancelled;
52}
53
54int __xen_suspend(int fast_suspend)
55{
56        int err, suspend_cancelled, nr_cpus;
57        struct ap_suspend_info info;
58
59        xenbus_suspend();
60
61        preempt_disable();
62
63        /* Prevent any races with evtchn_interrupt() handler. */
64        disable_irq(xen_platform_pdev->irq);
65
66        info.do_spin = 1;
67        atomic_set(&info.nr_spinning, 0);
68        smp_mb();
69
70        nr_cpus = num_online_cpus() - 1;
71
72        err = smp_call_function(ap_suspend, &info, 0, 0);
73        if (err < 0) {
74                preempt_enable();
75                xenbus_suspend_cancel();
76                return err;
77        }
78
79        while (atomic_read(&info.nr_spinning) != nr_cpus)
80                cpu_relax();
81
82        local_irq_disable();
83        suspend_cancelled = bp_suspend();
84        local_irq_enable();
85
86        smp_mb();
87        info.do_spin = 0;
88        while (atomic_read(&info.nr_spinning) != 0)
89                cpu_relax();
90
91        enable_irq(xen_platform_pdev->irq);
92
93        preempt_enable();
94
95        if (!suspend_cancelled)
96                xenbus_resume();
97        else
98                xenbus_suspend_cancel();
99
100        return 0;
101}
Note: See TracBrowser for help on using the repository browser.