Commit ee339fe6 authored by Konrad Rzeszutek Wilk's avatar Konrad Rzeszutek Wilk

xen/pci: Move check for acpi_sci_override_gsi to xen_setup_acpi_sci.

Previously we would check for acpi_sci_override_gsi == gsi every time
a PCI device was enabled. That works during early bootup, but later
on it could lead to triggering unnecessarily the acpi_gsi_to_irq(..) lookup.
The reason is that acpi_sci_override_gsi was declared in __initdata and
after early bootup could contain bogus values.

This patch moves the check for acpi_sci_override_gsi to the
site where the ACPI SCI is preset.

CC: stable@kernel.org
Reported-by: default avatarRaghavendra D Prabhu <rprabhu@wnohang.net>
Tested-by: default avatarRaghavendra D Prabhu <rprabhu@wnohang.net>
[http://lists.xensource.com/archives/html/xen-devel/2011-07/msg00154.html]
Suggested-by: default avatarIan Campbell <ijc@hellion.org.uk>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 155a16f2
...@@ -327,13 +327,12 @@ int __init pci_xen_hvm_init(void) ...@@ -327,13 +327,12 @@ int __init pci_xen_hvm_init(void)
} }
#ifdef CONFIG_XEN_DOM0 #ifdef CONFIG_XEN_DOM0
static int xen_register_pirq(u32 gsi, int triggering) static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
{ {
int rc, pirq, irq = -1; int rc, pirq, irq = -1;
struct physdev_map_pirq map_irq; struct physdev_map_pirq map_irq;
int shareable = 0; int shareable = 0;
char *name; char *name;
bool gsi_override = false;
if (!xen_pv_domain()) if (!xen_pv_domain())
return -1; return -1;
...@@ -345,31 +344,12 @@ static int xen_register_pirq(u32 gsi, int triggering) ...@@ -345,31 +344,12 @@ static int xen_register_pirq(u32 gsi, int triggering)
shareable = 1; shareable = 1;
name = "ioapic-level"; name = "ioapic-level";
} }
pirq = xen_allocate_pirq_gsi(gsi); pirq = xen_allocate_pirq_gsi(gsi);
if (pirq < 0) if (pirq < 0)
goto out; goto out;
/* Before we bind the GSI to a Linux IRQ, check whether if (gsi_override >= 0)
* we need to override it with bus_irq (IRQ) value. Usually for irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
* 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 else
irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name); irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
if (irq < 0) if (irq < 0)
...@@ -392,7 +372,7 @@ static int xen_register_pirq(u32 gsi, int triggering) ...@@ -392,7 +372,7 @@ static int xen_register_pirq(u32 gsi, int triggering)
return irq; return irq;
} }
static int xen_register_gsi(u32 gsi, int triggering, int polarity) static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
{ {
int rc, irq; int rc, irq;
struct physdev_setup_gsi setup_gsi; struct physdev_setup_gsi setup_gsi;
...@@ -403,7 +383,7 @@ static int xen_register_gsi(u32 gsi, int triggering, int polarity) ...@@ -403,7 +383,7 @@ static int xen_register_gsi(u32 gsi, int triggering, int polarity)
printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n", printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
gsi, triggering, polarity); gsi, triggering, polarity);
irq = xen_register_pirq(gsi, triggering); irq = xen_register_pirq(gsi, gsi_override, triggering);
setup_gsi.gsi = gsi; setup_gsi.gsi = gsi;
setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1); setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
...@@ -425,6 +405,8 @@ static __init void xen_setup_acpi_sci(void) ...@@ -425,6 +405,8 @@ static __init void xen_setup_acpi_sci(void)
int rc; int rc;
int trigger, polarity; int trigger, polarity;
int gsi = acpi_sci_override_gsi; int gsi = acpi_sci_override_gsi;
int irq = -1;
int gsi_override = -1;
if (!gsi) if (!gsi)
return; return;
...@@ -441,7 +423,25 @@ static __init void xen_setup_acpi_sci(void) ...@@ -441,7 +423,25 @@ static __init void xen_setup_acpi_sci(void)
printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d " printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
"polarity=%d\n", gsi, trigger, polarity); "polarity=%d\n", gsi, trigger, polarity);
gsi = xen_register_gsi(gsi, trigger, polarity); /* 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).
*/
/* Check whether the GSI != IRQ */
if (acpi_gsi_to_irq(gsi, &irq) == 0) {
if (irq >= 0 && irq != gsi)
/* Bugger, we MUST have that IRQ. */
gsi_override = irq;
}
gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
printk(KERN_INFO "xen: acpi sci %d\n", gsi); printk(KERN_INFO "xen: acpi sci %d\n", gsi);
return; return;
...@@ -450,7 +450,7 @@ static __init void xen_setup_acpi_sci(void) ...@@ -450,7 +450,7 @@ static __init void xen_setup_acpi_sci(void)
static int acpi_register_gsi_xen(struct device *dev, u32 gsi, static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
int trigger, int polarity) int trigger, int polarity)
{ {
return xen_register_gsi(gsi, trigger, polarity); return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
} }
static int __init pci_xen_initial_domain(void) static int __init pci_xen_initial_domain(void)
...@@ -489,7 +489,7 @@ void __init xen_setup_pirqs(void) ...@@ -489,7 +489,7 @@ void __init xen_setup_pirqs(void)
if (acpi_get_override_irq(irq, &trigger, &polarity) == -1) if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
continue; continue;
xen_register_pirq(irq, xen_register_pirq(irq, -1 /* no GSI override */,
trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE); trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment