Module Name: src Committed By: jmcneill Date: Sat Aug 13 20:07:13 UTC 2022
Modified Files: src/sys/arch/arm/acpi: acpi_pci_machdep.c Log Message: arm: acpi: Improve legacy INTx support. For devices on a bus with no direct _PRT, use the raw intr pin with the parent bridge's slot number to derive a pin number that can be used to lookup the pin -> irq mapping in the parent bus's _PRT. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/sys/arch/arm/acpi/acpi_pci_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/acpi/acpi_pci_machdep.c diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.21 src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.22 --- src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.21 Tue Dec 21 11:02:38 2021 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.c Sat Aug 13 20:07:13 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.c,v 1.21 2021/12/21 11:02:38 skrll Exp $ */ +/* $NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $ */ /*- * Copyright (c) 2018, 2020 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.21 2021/12/21 11:02:38 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.22 2022/08/13 20:07:13 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -71,6 +71,8 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_pci_mac struct acpi_pci_prt { u_int prt_segment; u_int prt_bus; + u_int prt_bridge_dev; + bool prt_derived; ACPI_HANDLE prt_handle; TAILQ_ENTRY(acpi_pci_prt) prt_list; }; @@ -210,6 +212,8 @@ acpi_pci_md_attach_hook(device_t parent, struct acpi_devnode *ad; ACPI_HANDLE handle; int seg, bus, dev, func; + u_int bridge_dev = 0; + bool derived = false; seg = ap->ap_seg; handle = NULL; @@ -225,10 +229,13 @@ acpi_pci_md_attach_hook(device_t parent, if (ad != NULL) { handle = ad->ad_handle; } else { - /* No routes defined for this bus, copy from parent */ + /* No routes defined for this bus, derive from parent */ TAILQ_FOREACH(prtp, &acpi_pci_irq_routes, prt_list) - if (prtp->prt_bus == bus) { + if (prtp->prt_bus == bus && + prtp->prt_segment == seg) { handle = prtp->prt_handle; + bridge_dev = dev; + derived = true; break; } } @@ -244,8 +251,10 @@ acpi_pci_md_attach_hook(device_t parent, if (handle != NULL) { prt = kmem_alloc(sizeof(*prt), KM_SLEEP); prt->prt_bus = pba->pba_bus; - prt->prt_segment = ap->ap_seg; + prt->prt_segment = seg; prt->prt_handle = handle; + prt->prt_bridge_dev = bridge_dev; + prt->prt_derived = derived; TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); } @@ -375,6 +384,7 @@ acpi_pci_md_intr_map(const struct pci_at ACPI_HANDLE linksrc; ACPI_BUFFER buf; void *linkdev; + u_int pin; if (pa->pa_intrpin == PCI_INTERRUPT_PIN_NONE) return EINVAL; @@ -386,6 +396,21 @@ acpi_pci_md_intr_map(const struct pci_at if (ACPI_FAILURE(acpi_get(prt->prt_handle, &buf, AcpiGetIrqRoutingTable))) return EIO; + /* + * For busses with no direct _PRT entry, derive the pin from the + * parent bridge. + */ + if (prt->prt_derived) { + pin = (((pa->pa_rawintrpin + prt->prt_bridge_dev) - 1) % 4) + 1; + } else { + pin = pa->pa_intrpin; + } + + aprint_debug("%s: bus=%u pin=%u pa_rawintrpin=%u pa_intrpin=%u " + "pa_intrswiz=%u prt_bridge_dev=%u\n", + __func__, pa->pa_bus, pin, pa->pa_rawintrpin, + pa->pa_intrpin, pa->pa_intrswiz, prt->prt_bridge_dev); + error = ENOENT; for (char *p = buf.Pointer; ; p += tab->Length) { tab = (ACPI_PCI_ROUTING_TABLE *)p; @@ -393,7 +418,7 @@ acpi_pci_md_intr_map(const struct pci_at break; if (pa->pa_device == ACPI_HIWORD(tab->Address) && - (pa->pa_intrpin - 1) == (tab->Pin & 3)) { + (pin - 1) == (tab->Pin & 3)) { if (tab->Source[0] != 0) { if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, tab->Source, &linksrc))) goto done;