ACPI/PCI: pci_link: penalize SCI correctly
Ondrej reported that IRQs stopped working in v4.7 on several
platforms. A typical scenario, from Ondrej's VT82C694X/694X, is:
ACPI: Using PIC for interrupt routing
ACPI: PCI Interrupt Link [LNKA] (IRQs 1 3 4 5 6 7 10 *11 12 14 15)
ACPI: No IRQ available for PCI Interrupt Link [LNKA]
8139too 0000:00:0f.0: PCI INT A: no GSI
We're using PIC routing, so acpi_irq_balance == 0, and LNKA is already
active at IRQ 11. In that case, acpi_pci_link_allocate() only tries
to use the active IRQ (IRQ 11) which also happens to be the SCI.
We should penalize the SCI by PIRQ_PENALTY_PCI_USING, but
irq_get_trigger_type(11) returns something other than
IRQ_TYPE_LEVEL_LOW, so we penalize it by PIRQ_PENALTY_ISA_ALWAYS
instead, which makes acpi_pci_link_allocate() assume the IRQ isn't
available and give up.
Add acpi_penalize_sci_irq() so platforms can tell us the SCI IRQ,
trigger, and polarity directly and we don't have to depend on
irq_get_trigger_type().
Fixes: 103544d869
(ACPI,PCI,IRQ: reduce resource requirements)
Link: http://lkml.kernel.org/r/201609251512.05657.linux@rainbow-software.org
Reported-by: Ondrej Zary <linux@rainbow-software.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Tested-by: Jonathan Liu <net147@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
eeaed4bb5a
commit
f1caa61df2
|
@ -454,6 +454,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
|
||||||
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||||
|
|
||||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||||
|
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stash over-ride to indicate we've been here
|
* stash over-ride to indicate we've been here
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct acpi_pci_link {
|
||||||
|
|
||||||
static LIST_HEAD(acpi_link_list);
|
static LIST_HEAD(acpi_link_list);
|
||||||
static DEFINE_MUTEX(acpi_link_lock);
|
static DEFINE_MUTEX(acpi_link_lock);
|
||||||
|
static int sci_irq = -1, sci_penalty;
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
PCI Link Device Management
|
PCI Link Device Management
|
||||||
|
@ -496,25 +497,13 @@ static int acpi_irq_get_penalty(int irq)
|
||||||
{
|
{
|
||||||
int penalty = 0;
|
int penalty = 0;
|
||||||
|
|
||||||
/*
|
if (irq == sci_irq)
|
||||||
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
|
penalty += sci_penalty;
|
||||||
* with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
|
|
||||||
* use for PCI IRQs.
|
|
||||||
*/
|
|
||||||
if (irq == acpi_gbl_FADT.sci_interrupt) {
|
|
||||||
u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
|
|
||||||
|
|
||||||
if (type != IRQ_TYPE_LEVEL_LOW)
|
|
||||||
penalty += PIRQ_PENALTY_ISA_ALWAYS;
|
|
||||||
else
|
|
||||||
penalty += PIRQ_PENALTY_PCI_USING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (irq < ACPI_MAX_ISA_IRQS)
|
if (irq < ACPI_MAX_ISA_IRQS)
|
||||||
return penalty + acpi_isa_irq_penalty[irq];
|
return penalty + acpi_isa_irq_penalty[irq];
|
||||||
|
|
||||||
penalty += acpi_irq_pci_sharing_penalty(irq);
|
return penalty + acpi_irq_pci_sharing_penalty(irq);
|
||||||
return penalty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init acpi_irq_penalty_init(void)
|
int __init acpi_irq_penalty_init(void)
|
||||||
|
@ -881,6 +870,17 @@ bool acpi_isa_irq_available(int irq)
|
||||||
acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
|
acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
|
||||||
|
{
|
||||||
|
sci_irq = irq;
|
||||||
|
|
||||||
|
if (trigger == ACPI_MADT_TRIGGER_LEVEL &&
|
||||||
|
polarity == ACPI_MADT_POLARITY_ACTIVE_LOW)
|
||||||
|
sci_penalty = PIRQ_PENALTY_PCI_USING;
|
||||||
|
else
|
||||||
|
sci_penalty = PIRQ_PENALTY_ISA_ALWAYS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Over-ride default table to reserve additional IRQs for use by ISA
|
* Over-ride default table to reserve additional IRQs for use by ISA
|
||||||
* e.g. acpi_irq_isa=5
|
* e.g. acpi_irq_isa=5
|
||||||
|
|
|
@ -326,6 +326,7 @@ struct pci_dev;
|
||||||
int acpi_pci_irq_enable (struct pci_dev *dev);
|
int acpi_pci_irq_enable (struct pci_dev *dev);
|
||||||
void acpi_penalize_isa_irq(int irq, int active);
|
void acpi_penalize_isa_irq(int irq, int active);
|
||||||
bool acpi_isa_irq_available(int irq);
|
bool acpi_isa_irq_available(int irq);
|
||||||
|
void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
|
||||||
void acpi_pci_irq_disable (struct pci_dev *dev);
|
void acpi_pci_irq_disable (struct pci_dev *dev);
|
||||||
|
|
||||||
extern int ec_read(u8 addr, u8 *val);
|
extern int ec_read(u8 addr, u8 *val);
|
||||||
|
|
Loading…
Reference in New Issue