aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
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 /arch/x86/pci
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>
Diffstat (limited to 'arch/x86/pci')
-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 8214724ce54d..fe008309ffec 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)
333 struct physdev_map_pirq map_irq; 333 struct physdev_map_pirq map_irq;
334 int shareable = 0; 334 int shareable = 0;
335 char *name; 335 char *name;
336 bool gsi_override = false;
336 337
337 if (!xen_pv_domain()) 338 if (!xen_pv_domain())
338 return -1; 339 return -1;
@@ -349,11 +350,32 @@ static int xen_register_pirq(u32 gsi, int triggering)
349 if (pirq < 0) 350 if (pirq < 0)
350 goto out; 351 goto out;
351 352
352 irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); 353 /* Before we bind the GSI to a Linux IRQ, check whether
354 * we need to override it with bus_irq (IRQ) value. Usually for
355 * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
356 * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
357 * but there are oddballs where the IRQ != GSI:
358 * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
359 * which ends up being: gsi_to_irq[9] == 20
360 * (which is what acpi_gsi_to_irq ends up calling when starting the
361 * the ACPI interpreter and keels over since IRQ 9 has not been
362 * setup as we had setup IRQ 20 for it).
363 */
364 if (gsi == acpi_sci_override_gsi) {
365 /* Check whether the GSI != IRQ */
366 acpi_gsi_to_irq(gsi, &irq);
367 if (irq != gsi)
368 /* Bugger, we MUST have that IRQ. */
369 gsi_override = true;
370 }
371 if (gsi_override)
372 irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name);
373 else
374 irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
353 if (irq < 0) 375 if (irq < 0)
354 goto out; 376 goto out;
355 377
356 printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq); 378 printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
357 379
358 map_irq.domid = DOMID_SELF; 380 map_irq.domid = DOMID_SELF;
359 map_irq.type = MAP_PIRQ_TYPE_GSI; 381 map_irq.type = MAP_PIRQ_TYPE_GSI;