--- a/sys/dev/acpica/acpi_pci_link.c +++ b/sys/dev/acpica/acpi_pci_link.c @@ -232,6 +232,16 @@ break; case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + if (req->link_index >= req->sc->pl_num_links) { + /* + * _CRS returned more IRQ resources than the + * counting walk saw (stateful method). + */ + device_printf(req->sc->pl_dev, + "_CRS returned more IRQ resources than counted\n"); + req->res_index++; + break; + } KASSERT(req->link_index < req->sc->pl_num_links, ("%s: array boundary violation", __func__)); link = &req->sc->pl_links[req->link_index]; @@ -308,6 +318,16 @@ if (req->in_dpf == DPF_IGNORE) break; + if (req->link_index >= req->sc->pl_num_links) { + /* + * _PRS returned more IRQ resources than were + * counted (stateful or _CRS/_PRS mismatch). + */ + device_printf(req->sc->pl_dev, + "_PRS returned more IRQ resources than counted\n"); + req->res_index++; + break; + } KASSERT(req->link_index < req->sc->pl_num_links, ("%s: array boundary violation", __func__)); link = &req->sc->pl_links[req->link_index]; @@ -764,7 +784,8 @@ in_dpf = DPF_OUTSIDE; break; case ACPI_RESOURCE_TYPE_IRQ: - KKASSERT(i < sc->pl_num_links); + if (i >= sc->pl_num_links) + break; /* more IRQ resources than links */ res->Data.Irq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) { KASSERT(link->l_irq < NUM_ISA_INTERRUPTS, @@ -777,7 +798,8 @@ i++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - KKASSERT(i < sc->pl_num_links); + if (i >= sc->pl_num_links) + break; /* more IRQ resources than links */ res->Data.ExtendedIrq.InterruptCount = 1; if (PCI_INTERRUPT_VALID(link->l_irq)) res->Data.ExtendedIrq.Interrupts[0] = @@ -893,7 +915,8 @@ switch (resource->Type) { case ACPI_RESOURCE_TYPE_IRQ: case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - KKASSERT(i < sc->pl_num_links); + if (i >= sc->pl_num_links) + break; /* more IRQ resources than links */ /* * Only configure the interrupt and update the @@ -1009,6 +1032,8 @@ best_weight = INT_MAX; for (i = 0; i < link->l_num_irqs; i++) { pos_irq = link->l_irqs[i]; + if (pos_irq < 0 || pos_irq >= NUM_ACPI_INTERRUPTS) + continue; if (pos_irq < NUM_ISA_INTERRUPTS && (pci_link_bios_isa_irqs & 1 << pos_irq) == 0) continue; @@ -1023,7 +1048,8 @@ * If this is an ISA IRQ and SCI could be shared, try using * the SCI as a fallback. */ - if (link->l_isa_irq && acpi_sci_pci_shareable()) { + if (link->l_isa_irq && AcpiGbl_FADT.SciInterrupt < NUM_ACPI_INTERRUPTS && + acpi_sci_pci_shareable()) { pos_irq = AcpiGbl_FADT.SciInterrupt; pos_weight = pci_link_interrupt_weights[pos_irq]; if (pos_weight < best_weight) {