ia64/xen-unstable

view unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c @ 18824:0b8c6c91c5a4

pv-on-hvm drivers: build fixes for Linux 2.6.27+

Make the drivers build properly in a 2.6.27 environment as well as
against a kernel with pv-ops Xen configured on (in the latter case
more work would be needed to also make the drivers work, as there's a
large number of duplicate exports).

Portions from Charles Arnold <carnold@novell.com>.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Nov 24 11:11:20 2008 +0000 (2008-11-24)
parents 459f7ca6cf2a
children
line source
1 #include <linux/cpumask.h>
2 #include <linux/preempt.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>
9 struct ap_suspend_info {
10 int do_spin;
11 atomic_t nr_spinning;
12 };
14 #ifdef CONFIG_SMP
16 /*
17 * Spinning prevents, for example, APs touching grant table entries while
18 * the shared grant table is not mapped into the address space imemdiately
19 * after resume.
20 */
21 static void ap_suspend(void *_info)
22 {
23 struct ap_suspend_info *info = _info;
25 BUG_ON(!irqs_disabled());
27 atomic_inc(&info->nr_spinning);
28 mb();
30 while (info->do_spin)
31 cpu_relax();
33 mb();
34 atomic_dec(&info->nr_spinning);
35 }
37 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
38 #define initiate_ap_suspend(i) smp_call_function(ap_suspend, i, 0, 0)
39 #else
40 #define initiate_ap_suspend(i) smp_call_function(ap_suspend, i, 0)
41 #endif
43 #else /* !defined(CONFIG_SMP) */
45 #define initiate_ap_suspend(i) 0
47 #endif
49 static int bp_suspend(void)
50 {
51 int suspend_cancelled;
53 BUG_ON(!irqs_disabled());
55 suspend_cancelled = HYPERVISOR_suspend(0);
57 if (!suspend_cancelled) {
58 platform_pci_resume();
59 gnttab_resume();
60 irq_resume();
61 }
63 return suspend_cancelled;
64 }
66 int __xen_suspend(int fast_suspend, void (*resume_notifier)(int))
67 {
68 int err, suspend_cancelled, nr_cpus;
69 struct ap_suspend_info info;
71 xenbus_suspend();
73 preempt_disable();
75 /* Prevent any races with evtchn_interrupt() handler. */
76 disable_irq(xen_platform_pdev->irq);
78 info.do_spin = 1;
79 atomic_set(&info.nr_spinning, 0);
80 smp_mb();
82 nr_cpus = num_online_cpus() - 1;
84 err = initiate_ap_suspend(&info);
85 if (err < 0) {
86 preempt_enable();
87 xenbus_suspend_cancel();
88 return err;
89 }
91 while (atomic_read(&info.nr_spinning) != nr_cpus)
92 cpu_relax();
94 local_irq_disable();
95 suspend_cancelled = bp_suspend();
96 resume_notifier(suspend_cancelled);
97 local_irq_enable();
99 smp_mb();
100 info.do_spin = 0;
101 while (atomic_read(&info.nr_spinning) != 0)
102 cpu_relax();
104 enable_irq(xen_platform_pdev->irq);
106 preempt_enable();
108 if (!suspend_cancelled)
109 xenbus_resume();
110 else
111 xenbus_suspend_cancel();
113 return 0;
114 }