summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-06-30 09:18:27 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-06-30 11:23:39 -0400
commit155a16f21923bc2f04161ac92acca986371ef27b (patch)
tree758eb5a34e49ac7323d5d7f076a5fd7f268bfe73
parent32dd11942aeb47f91209a446d6b10063c5b69389 (diff)
xen/pci: Use the INT_SRC_OVR IRQ (instead of GSI) to preset the ACPI SCI IRQ.
In the past we would use the GSI value to preset the ACPI SCI IRQ which worked great as GSI == IRQ: ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) While that is most often seen, there are some oddities: ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level) which means that GSI 20 (or pin 20) is to be overriden for IRQ 9. Our code that presets the interrupt for ACPI SCI however would use the GSI 20 instead of IRQ 9 ending up with: xen: sci override: global_irq=20 trigger=0 polarity=1 xen: registering gsi 20 triggering 0 polarity 1 xen: --> pirq=20 -> irq=20 xen: acpi sci 20 .. snip.. calling acpi_init+0x0/0xbc @ 1 ACPI: SCI (IRQ9) allocation failed ACPI Exception: AE_NOT_ACQUIRED, Unable to install System Control Interrupt handler (20110413/evevent-119) ACPI: Unable to start the ACPI Interpreter as the ACPI interpreter made a call to 'acpi_gsi_to_irq' which got nine. It used that value to request an IRQ (request_irq) and since that was not present it failed. The fix is to recognize that for interrupts that are overriden (in our case we only care about the ACPI SCI) we should use the IRQ number to present the IRQ instead of the using GSI. End result is that we get: xen: sci override: global_irq=20 trigger=0 polarity=1 xen: registering gsi 20 triggering 0 polarity 1 xen: --> pirq=20 -> irq=9 (gsi=9) xen: acpi sci 9 which fixes the ACPI interpreter failing on startup. CC: stable@kernel.org Reported-by: Liwei <xieliwei@gmail.com> Tested-by: Liwei <xieliwei@gmail.com> [http://lists.xensource.com/archives/html/xen-devel/2011-06/msg01727.html] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--arch/x86/pci/xen.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 8214724ce54..fe008309ffe 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -333,6 +333,7 @@ static int xen_register_pirq(u32 gsi, int triggering)
struct physdev_map_pirq map_irq;
int shareable = 0;
char *name;
+ bool gsi_override = false;
if (!xen_pv_domain())
return -1;
@@ -349,11 +350,32 @@ static int xen_register_pirq(u32 gsi, int triggering)
if (pirq < 0)
goto out;
- irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
+ /* Before we bind the GSI to a Linux IRQ, check whether
+ * we need to override it with bus_irq (IRQ) value. Usually for
+ * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
+ * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
+ * but there are oddballs where the IRQ != GSI:
+ * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
+ * which ends up being: gsi_to_irq[9] == 20
+ * (which is what acpi_gsi_to_irq ends up calling when starting the
+ * the ACPI interpreter and keels over since IRQ 9 has not been
+ * setup as we had setup IRQ 20 for it).
+ */
+ if (gsi == acpi_sci_override_gsi) {
+ /* Check whether the GSI != IRQ */
+ acpi_gsi_to_irq(gsi, &irq);
+ if (irq != gsi)
+ /* Bugger, we MUST have that IRQ. */
+ gsi_override = true;
+ }
+ if (gsi_override)
+ irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name);
+ else
+ irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
if (irq < 0)
goto out;
- printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
+ printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
map_irq.domid = DOMID_SELF;
map_irq.type = MAP_PIRQ_TYPE_GSI;