aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-05-21 16:54:10 +0100
committerBen Hutchings <ben@decadent.org.uk>2012-05-31 00:44:01 +0100
commit482953eeea949295981474e179d37fd61258d3ca (patch)
treeb2d56e673e88c9b92516c5d1f78b2d8279557ccb
parent22d3eb7b84cfd93141ddde38fcbabcd190eb5f1f (diff)
xen: do not map the same GSI twice in PVHVM guests.
commit 68c2c39a76b094e9b2773e5846424ea674bf2c46 upstream. PV on HVM guests map GSIs into event channels. At restore time the event channels are resumed by restore_pirqs. Device drivers might try to register the same GSI again through ACPI at restore time, but the GSI has already been mapped and bound by restore_pirqs. This patch detects these situations and avoids mapping the same GSI multiple times. Without this patch we get: (XEN) irq.c:2235: dom4: pirq 23 or emuirq 28 already mapped and waste a pirq. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--arch/x86/pci/xen.c4
-rw-r--r--drivers/xen/events.c5
-rw-r--r--include/xen/events.h3
3 files changed, 10 insertions, 2 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index d99346ea8fd..4c262f6ff7c 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -64,6 +64,10 @@ static int xen_register_pirq(u32 gsi, int gsi_override, int triggering,
int shareable = 0;
char *name;
+ irq = xen_irq_from_gsi(gsi);
+ if (irq > 0)
+ return irq;
+
if (set_pirq)
pirq = gsi;
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 6e075cdd0c6..fec12048c2c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -600,7 +600,7 @@ static void disable_pirq(struct irq_data *data)
disable_dynirq(data);
}
-static int find_irq_by_gsi(unsigned gsi)
+int xen_irq_from_gsi(unsigned gsi)
{
struct irq_info *info;
@@ -614,6 +614,7 @@ static int find_irq_by_gsi(unsigned gsi)
return -1;
}
+EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
/*
* Do not make any assumptions regarding the relationship between the
@@ -633,7 +634,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
mutex_lock(&irq_mapping_update_lock);
- irq = find_irq_by_gsi(gsi);
+ irq = xen_irq_from_gsi(gsi);
if (irq != -1) {
printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
irq, gsi);
diff --git a/include/xen/events.h b/include/xen/events.h
index d287997d3ea..8f3d6225122 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -96,6 +96,9 @@ int xen_irq_from_pirq(unsigned pirq);
/* Return the pirq allocated to the irq. */
int xen_pirq_from_irq(unsigned irq);
+/* Return the irq allocated to the gsi */
+int xen_irq_from_gsi(unsigned gsi);
+
/* Determine whether to ignore this IRQ if it is passed to a guest. */
int xen_test_irq_shared(int irq);