Index: sys/dev/pci/pci_host_generic_acpi.c =================================================================== --- sys/dev/pci/pci_host_generic_acpi.c +++ sys/dev/pci/pci_host_generic_acpi.c @@ -348,14 +348,52 @@ return (acpi_pcib_route_interrupt(bus, dev, pin, &sc->ap_prt)); } +static u_int +generic_pcie_get_xref(device_t pci, device_t child) +{ + struct generic_pcie_acpi_softc *sc; + uintptr_t rid; + u_int xref, devid; + int err; + + sc = device_get_softc(pci); + err = pcib_get_id(pci, child, PCI_ID_RID, &rid); + if (err != 0) + return (ACPI_MSI_XREF); + err = acpi_iort_map_pci_msi(sc->base.ecam, rid, &xref, &devid); + if (err != 0) + return (ACPI_MSI_XREF); + return (xref); +} + +static u_int +generic_pcie_map_id(device_t pci, device_t child, uintptr_t *id) +{ + struct generic_pcie_acpi_softc *sc; + uintptr_t rid; + u_int xref, devid; + int err; + + sc = device_get_softc(pci); + err = pcib_get_id(pci, child, PCI_ID_RID, &rid); + if (err != 0) + return (err); + err = acpi_iort_map_pci_msi(sc->base.ecam, rid, &xref, &devid); + if (err == 0) + *id = devid; + else + *id = rid; /* RID not in IORT, likely FW bug, ignore */ + return (0); +} + static int generic_pcie_acpi_alloc_msi(device_t pci, device_t child, int count, int maxcount, int *irqs) { #if defined(INTRNG) - return (intr_alloc_msi(pci, child, ACPI_MSI_XREF, count, maxcount, - irqs)); + return (intr_alloc_msi(pci, child, generic_pcie_get_xref(pci, child), + count, maxcount, irqs)); #else return (ENXIO); #endif @@ -367,7 +405,8 @@ { #if defined(INTRNG) - return (intr_release_msi(pci, child, ACPI_MSI_XREF, count, irqs)); + return (intr_release_msi(pci, child, generic_pcie_get_xref(pci, child), + count, irqs)); #else return (ENXIO); #endif @@ -379,7 +418,8 @@ { #if defined(INTRNG) - return (intr_map_msi(pci, child, ACPI_MSI_XREF, irq, addr, data)); + return (intr_map_msi(pci, child, generic_pcie_get_xref(pci, child), irq, + addr, data)); #else return (ENXIO); #endif @@ -390,7 +430,8 @@ { #if defined(INTRNG) - return (intr_alloc_msix(pci, child, ACPI_MSI_XREF, irq)); + return (intr_alloc_msix(pci, child, generic_pcie_get_xref(pci, child), + irq)); #else return (ENXIO); #endif @@ -401,7 +442,8 @@ { #if defined(INTRNG) - return (intr_release_msix(pci, child, ACPI_MSI_XREF, irq)); + return (intr_release_msix(pci, child, generic_pcie_get_xref(pci, child), + irq)); #else return (ENXIO); #endif @@ -412,14 +454,8 @@ uintptr_t *id) { - /* - * Use the PCI RID to find the MSI ID for now, we support only 1:1 - * mapping - * - * On aarch64, more complex mapping would come from IORT table - */ if (type == PCI_ID_MSI) - return (pcib_get_id(pci, child, PCI_ID_RID, id)); + return (generic_pcie_map_id(pci, child, id)); else return (pcib_get_id(pci, child, type, id)); }