Skip to content

Commit f1caa61

Browse files
Sinan Kayarafaeljw
authored andcommitted
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: 103544d (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>
1 parent eeaed4b commit f1caa61

3 files changed

Lines changed: 17 additions & 15 deletions

File tree

arch/x86/kernel/acpi/boot.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
454454
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
455455

456456
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
457+
acpi_penalize_sci_irq(bus_irq, trigger, polarity);
457458

458459
/*
459460
* stash over-ride to indicate we've been here

drivers/acpi/pci_link.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct acpi_pci_link {
8787

8888
static LIST_HEAD(acpi_link_list);
8989
static DEFINE_MUTEX(acpi_link_lock);
90+
static int sci_irq = -1, sci_penalty;
9091

9192
/* --------------------------------------------------------------------------
9293
PCI Link Device Management
@@ -496,25 +497,13 @@ static int acpi_irq_get_penalty(int irq)
496497
{
497498
int penalty = 0;
498499

499-
/*
500-
* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
501-
* with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
502-
* use for PCI IRQs.
503-
*/
504-
if (irq == acpi_gbl_FADT.sci_interrupt) {
505-
u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
506-
507-
if (type != IRQ_TYPE_LEVEL_LOW)
508-
penalty += PIRQ_PENALTY_ISA_ALWAYS;
509-
else
510-
penalty += PIRQ_PENALTY_PCI_USING;
511-
}
500+
if (irq == sci_irq)
501+
penalty += sci_penalty;
512502

513503
if (irq < ACPI_MAX_ISA_IRQS)
514504
return penalty + acpi_isa_irq_penalty[irq];
515505

516-
penalty += acpi_irq_pci_sharing_penalty(irq);
517-
return penalty;
506+
return penalty + acpi_irq_pci_sharing_penalty(irq);
518507
}
519508

520509
int __init acpi_irq_penalty_init(void)
@@ -881,6 +870,17 @@ bool acpi_isa_irq_available(int irq)
881870
acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
882871
}
883872

873+
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
874+
{
875+
sci_irq = irq;
876+
877+
if (trigger == ACPI_MADT_TRIGGER_LEVEL &&
878+
polarity == ACPI_MADT_POLARITY_ACTIVE_LOW)
879+
sci_penalty = PIRQ_PENALTY_PCI_USING;
880+
else
881+
sci_penalty = PIRQ_PENALTY_ISA_ALWAYS;
882+
}
883+
884884
/*
885885
* Over-ride default table to reserve additional IRQs for use by ISA
886886
* e.g. acpi_irq_isa=5

include/linux/acpi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ struct pci_dev;
326326
int acpi_pci_irq_enable (struct pci_dev *dev);
327327
void acpi_penalize_isa_irq(int irq, int active);
328328
bool acpi_isa_irq_available(int irq);
329+
void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
329330
void acpi_pci_irq_disable (struct pci_dev *dev);
330331

331332
extern int ec_read(u8 addr, u8 *val);

0 commit comments

Comments
 (0)