# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1189195055 21600
# Node ID 8aa8af371be0e9c46b22615ba7e8990ed738ea12
# Parent e1466633683cf0bdba9ef905d0a79702ba05a751
# Parent 2a214d4ef5b175708d01ac5ce15de7745c48b756
merge with linux-2.6.18-xen.hg (staging)
---
drivers/acpi/hardware/hwsleep.c | 13 ++++++--
drivers/xen/core/evtchn.c | 19 ++++++------
drivers/xen/core/gnttab.c | 9 +++++-
drivers/xen/core/reboot.c | 36 ++++++++++--------------
drivers/xen/evtchn/evtchn.c | 59 ++++++++++++++++++++++++++++++++++++++++
include/xen/evtchn.h | 12 ++++++++
include/xen/gnttab.h | 6 ----
include/xen/xenbus.h | 1
8 files changed, 114 insertions(+), 41 deletions(-)
diff -r e1466633683c -r 8aa8af371be0 drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c Thu Sep 06 14:33:25 2007 -0600
+++ b/drivers/acpi/hardware/hwsleep.c Fri Sep 07 13:57:35 2007 -0600
@@ -338,10 +338,6 @@ acpi_status asmlinkage acpi_enter_sleep_
status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
ACPI_REGISTER_PM1B_CONTROL,
PM1Bcontrol);
-#else
- status = acpi_notify_hypervisor_state(sleep_state,
- PM1Acontrol, PM1Bcontrol);
-#endif
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
@@ -383,6 +379,15 @@ acpi_status asmlinkage acpi_enter_sleep_
} while (!in_value);
return_ACPI_STATUS(AE_OK);
+#else
+ /* PV ACPI just need check hypercall return value */
+ status = acpi_notify_hypervisor_state(sleep_state,
+ PM1Acontrol, PM1Bcontrol);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
+ else
+ return_ACPI_STATUS(AE_OK);
+#endif
}
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
diff -r e1466633683c -r 8aa8af371be0 drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Thu Sep 06 14:33:25 2007 -0600
+++ b/drivers/xen/core/evtchn.c Fri Sep 07 13:57:35 2007 -0600
@@ -125,12 +125,15 @@ static inline unsigned long active_evtch
~sh->evtchn_mask[idx]);
}
-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
-{
+void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
int irq = evtchn_to_irq[chn];
- BUG_ON(irq == -1);
- set_native_irq_info(irq, cpumask_of_cpu(cpu));
+ BUG_ON(!test_bit(chn, s->evtchn_mask));
+
+ if (irq != -1)
+ set_native_irq_info(irq, cpumask_of_cpu(cpu));
clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]);
set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]);
@@ -160,10 +163,6 @@ static inline unsigned long active_evtch
unsigned int idx)
{
return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]);
-}
-
-static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
-{
}
static void init_evtchn_cpu_bindings(void)
@@ -607,7 +606,7 @@ static void rebind_irq_to_cpu(unsigned i
* virq or IPI channel, which don't actually need to be rebound. Ignore
* it, but don't do the xenlinux-level rebind in that case.
*/
- if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) == 0)
bind_evtchn_to_cpu(evtchn, tcpu);
}
@@ -626,7 +625,7 @@ int resend_irq_on_evtchn(unsigned int ir
if (!VALID_EVTCHN(evtchn))
return 1;
- masked = synch_test_and_set_bit(evtchn, s->evtchn_mask);
+ masked = test_and_set_evtchn_mask(evtchn);
synch_set_bit(evtchn, s->evtchn_pending);
if (!masked)
unmask_evtchn(evtchn);
diff -r e1466633683c -r 8aa8af371be0 drivers/xen/core/gnttab.c
--- a/drivers/xen/core/gnttab.c Thu Sep 06 14:33:25 2007 -0600
+++ b/drivers/xen/core/gnttab.c Fri Sep 07 13:57:35 2007 -0600
@@ -587,7 +587,14 @@ out:
put_page(page);
return err;
}
-EXPORT_SYMBOL(gnttab_copy_grant_page);
+EXPORT_SYMBOL_GPL(gnttab_copy_grant_page);
+
+void gnttab_reset_grant_page(struct page *page)
+{
+ init_page_count(page);
+ reset_page_mapcount(page);
+}
+EXPORT_SYMBOL_GPL(gnttab_reset_grant_page);
/*
* Keep track of foreign pages marked as PageForeign so that we don't
diff -r e1466633683c -r 8aa8af371be0 drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c Thu Sep 06 14:33:25 2007 -0600
+++ b/drivers/xen/core/reboot.c Fri Sep 07 13:57:35 2007 -0600
@@ -8,7 +8,6 @@
#include <asm/hypervisor.h>
#include <xen/xenbus.h>
#include <linux/kmod.h>
-#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -68,36 +67,31 @@ static int shutdown_process(void *__unus
static int xen_suspend(void *__unused)
{
- int err = __xen_suspend(fast_suspend);
+ int err;
+
+ daemonize("suspend");
+ err = set_cpus_allowed(current, cpumask_of_cpu(0));
+ if (err) {
+ printk(KERN_ERR "Xen suspend can't run on CPU0 (%d)\n", err);
+ goto out;
+ }
+
+ err = __xen_suspend(fast_suspend);
if (err)
printk(KERN_ERR "Xen suspend failed (%d)\n", err);
+
+ out:
shutting_down = SHUTDOWN_INVALID;
return 0;
}
-static int kthread_create_on_cpu(int (*f)(void *arg),
- void *arg,
- const char *name,
- int cpu)
-{
- struct task_struct *p;
- p = kthread_create(f, arg, name);
- if (IS_ERR(p))
- return PTR_ERR(p);
- kthread_bind(p, cpu);
- wake_up_process(p);
- return 0;
-}
-
static void __shutdown_handler(void *unused)
{
int err;
- if (shutting_down != SHUTDOWN_SUSPEND)
- err = kernel_thread(shutdown_process, NULL,
- CLONE_FS | CLONE_FILES);
- else
- err = kthread_create_on_cpu(xen_suspend, NULL, "suspend", 0);
+ err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
+ xen_suspend : shutdown_process,
+ NULL, CLONE_FS | CLONE_FILES);
if (err < 0) {
printk(KERN_WARNING "Error creating shutdown process (%d): "
diff -r e1466633683c -r 8aa8af371be0 drivers/xen/evtchn/evtchn.c
--- a/drivers/xen/evtchn/evtchn.c Thu Sep 06 14:33:25 2007 -0600
+++ b/drivers/xen/evtchn/evtchn.c Fri Sep 07 13:57:35 2007 -0600
@@ -62,6 +62,9 @@ struct per_user_data {
/* Processes wait on this queue when ring is empty. */
wait_queue_head_t evtchn_wait;
struct fasync_struct *evtchn_async_queue;
+
+ int bind_cpu;
+ int nr_event_wrong_delivery;
};
/* Who's bound to each port? */
@@ -93,6 +96,45 @@ void evtchn_device_upcall(int port)
spin_unlock(&port_user_lock);
}
+static void evtchn_rebind_cpu(evtchn_port_t port, unsigned int cpu)
+{
+ struct evtchn_bind_vcpu ebv = { .port = port, .vcpu = cpu };
+ int masked;
+
+ masked = test_and_set_evtchn_mask(port);
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &ebv) == 0)
+ bind_evtchn_to_cpu(port, cpu);
+ if (!masked)
+ unmask_evtchn(port);
+}
+
+static void evtchn_check_wrong_delivery(struct per_user_data *u)
+{
+ evtchn_port_t port;
+ unsigned int current_cpu = smp_processor_id();
+
+ /* Delivered to correct CPU? All is good. */
+ if (u->bind_cpu == current_cpu) {
+ u->nr_event_wrong_delivery = 0;
+ return;
+ }
+
+ /* Tolerate up to 100 consecutive misdeliveries. */
+ if (++u->nr_event_wrong_delivery < 100)
+ return;
+
+ spin_lock_irq(&port_user_lock);
+
+ for (port = 0; port < NR_EVENT_CHANNELS; port++)
+ if (port_user[port] == u)
+ evtchn_rebind_cpu(port, current_cpu);
+
+ u->bind_cpu = current_cpu;
+ u->nr_event_wrong_delivery = 0;
+
+ spin_unlock_irq(&port_user_lock);
+}
+
static ssize_t evtchn_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -153,6 +195,8 @@ static ssize_t evtchn_read(struct file *
((bytes2 != 0) &&
copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
goto unlock_out;
+
+ evtchn_check_wrong_delivery(u);
u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
rc = bytes1 + bytes2;
@@ -202,9 +246,22 @@ static void evtchn_bind_to_user(struct p
static void evtchn_bind_to_user(struct per_user_data *u, int port)
{
spin_lock_irq(&port_user_lock);
+
BUG_ON(port_user[port] != NULL);
port_user[port] = u;
+
+ if (u->bind_cpu == -1) {
+ static unsigned int bind_cpu;
+ bind_cpu = next_cpu(bind_cpu, cpu_online_map);
+ if (bind_cpu >= NR_CPUS)
+ bind_cpu = first_cpu(cpu_online_map);
+ u->bind_cpu = bind_cpu;
+ }
+
+ evtchn_rebind_cpu(port, u->bind_cpu);
+
unmask_evtchn(port);
+
spin_unlock_irq(&port_user_lock);
}
@@ -385,6 +442,8 @@ static int evtchn_open(struct inode *ino
mutex_init(&u->ring_cons_mutex);
filp->private_data = u;
+
+ u->bind_cpu = -1;
return 0;
}
diff -r e1466633683c -r 8aa8af371be0 include/xen/evtchn.h
--- a/include/xen/evtchn.h Thu Sep 06 14:33:25 2007 -0600
+++ b/include/xen/evtchn.h Fri Sep 07 13:57:35 2007 -0600
@@ -104,6 +104,18 @@ void mask_evtchn(int port);
void mask_evtchn(int port);
void unmask_evtchn(int port);
+#ifdef CONFIG_SMP
+void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu);
+#else
+#define bind_evtchn_to_cpu(chn, cpu) ((void)0)
+#endif
+
+static inline int test_and_set_evtchn_mask(int port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ return synch_test_and_set_bit(port, s->evtchn_mask);
+}
+
static inline void clear_evtchn(int port)
{
shared_info_t *s = HYPERVISOR_shared_info;
diff -r e1466633683c -r 8aa8af371be0 include/xen/gnttab.h
--- a/include/xen/gnttab.h Thu Sep 06 14:33:25 2007 -0600
+++ b/include/xen/gnttab.h Fri Sep 07 13:57:35 2007 -0600
@@ -108,11 +108,7 @@ static inline void __gnttab_dma_unmap_pa
{
}
-static inline void gnttab_reset_grant_page(struct page *page)
-{
- init_page_count(page);
- reset_page_mapcount(page);
-}
+void gnttab_reset_grant_page(struct page *page);
int gnttab_suspend(void);
int gnttab_resume(void);
diff -r e1466633683c -r 8aa8af371be0 include/xen/xenbus.h
--- a/include/xen/xenbus.h Thu Sep 06 14:33:25 2007 -0600
+++ b/include/xen/xenbus.h Fri Sep 07 13:57:35 2007 -0600
@@ -39,6 +39,7 @@
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/init.h>
+#include <linux/err.h>
#include <xen/interface/xen.h>
#include <xen/interface/grant_table.h>
#include <xen/interface/io/xenbus.h>
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|