Skip to content

Commit

Permalink
Pull bugzilla-9153 into release branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Len Brown committed Nov 20, 2007
2 parents 86533e8 + 61fd47e commit 7833b4a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 11 deletions.
21 changes: 20 additions & 1 deletion arch/x86/kernel/io_apic_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ static int EISA_ELCR(unsigned int irq)
#define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0)

static int __init MPBIOS_polarity(int idx)
static int MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
int polarity;
Expand Down Expand Up @@ -2830,6 +2830,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
return 0;
}

int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
{
int i;

if (skip_ioapic_setup)
return -1;

for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].mpc_irqtype == mp_INT &&
mp_irqs[i].mpc_srcbusirq == bus_irq)
break;
if (i >= mp_irq_entries)
return -1;

*trigger = irq_trigger(i);
*polarity = irq_polarity(i);
return 0;
}

#endif /* CONFIG_ACPI */

static int __init parse_disable_timer_pin_1(char *arg)
Expand Down
24 changes: 22 additions & 2 deletions arch/x86/kernel/io_apic_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
#define default_PCI_trigger(idx) (1)
#define default_PCI_polarity(idx) (1)

static int __init MPBIOS_polarity(int idx)
static int MPBIOS_polarity(int idx)
{
int bus = mp_irqs[idx].mpc_srcbus;
int polarity;
Expand Down Expand Up @@ -2222,8 +2222,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
return 0;
}

#endif /* CONFIG_ACPI */

int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
{
int i;

if (skip_ioapic_setup)
return -1;

for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].mpc_irqtype == mp_INT &&
mp_irqs[i].mpc_srcbusirq == bus_irq)
break;
if (i >= mp_irq_entries)
return -1;

*trigger = irq_trigger(i);
*polarity = irq_polarity(i);
return 0;
}

#endif /* CONFIG_ACPI */

/*
* This function currently is only a helper for the i386 smp boot process where
Expand Down Expand Up @@ -2260,3 +2279,4 @@ void __init setup_ioapic_dest(void)
}
}
#endif

24 changes: 16 additions & 8 deletions drivers/pnp/pnpacpi/rsparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
{
int i = 0;
int irq;
int p, t;

if (!valid_IRQ(gsi))
return;
Expand All @@ -85,15 +86,22 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
if (i >= PNP_MAX_IRQ)
return;

#ifdef CONFIG_X86
if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE ||
polarity != ACPI_ACTIVE_HIGH)) {
pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, "
"active high", gsi);
triggering = ACPI_EDGE_SENSITIVE;
polarity = ACPI_ACTIVE_HIGH;
/*
* in IO-APIC mode, use overrided attribute. Two reasons:
* 1. BIOS bug in DSDT
* 2. BIOS uses IO-APIC mode Interrupt Source Override
*/
if (!acpi_get_override_irq(gsi, &t, &p)) {
t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;

if (triggering != t || polarity != p) {
pnp_warn("IRQ %d override to %s, %s",
gsi, t ? "edge":"level", p ? "low":"high");
triggering = t;
polarity = p;
}
}
#endif

res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
res->irq_resource[i].flags |= irq_flags(triggering, polarity);
Expand Down
5 changes: 5 additions & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ extern unsigned long acpi_realmode_flags;
int acpi_register_gsi (u32 gsi, int triggering, int polarity);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);

#ifdef CONFIG_X86_IO_APIC
extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity);
#else
#define acpi_get_override_irq(bus, trigger, polarity) (-1)
#endif
/*
* This function undoes the effect of one call to acpi_register_gsi().
* If this matches the last registration, any IRQ resources for gsi
Expand Down

0 comments on commit 7833b4a

Please sign in to comment.