From 09c29451d9bc40f8a97bbffd87ab42a7259df823 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 11 Aug 2018 22:47:27 +0000 Subject: [PATCH] Make legacy interrupts work in more cases. --- sys/arch/arm64/dev/acpipci.c | 45 ++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/sys/arch/arm64/dev/acpipci.c b/sys/arch/arm64/dev/acpipci.c index 954aaf8c9ab..5b067a254e8 100644 --- a/sys/arch/arm64/dev/acpipci.c +++ b/sys/arch/arm64/dev/acpipci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpipci.c,v 1.5 2018/08/11 20:46:48 kettenis Exp $ */ +/* $OpenBSD: acpipci.c,v 1.6 2018/08/11 22:47:27 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis * @@ -343,25 +343,52 @@ struct acpipci_intr_handle { int ih_msi; }; +int +acpipci_intr_swizzle(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + struct acpipci_intr_handle *ih; + int dev, swizpin; + + if (pa->pa_bridgetag == NULL) + return -1; + + pci_decompose_tag(pa->pa_pc, pa->pa_tag, NULL, &dev, NULL); + swizpin = PPB_INTERRUPT_SWIZZLE(pa->pa_rawintrpin, dev); + if ((void *)pa->pa_bridgeih[swizpin - 1] == NULL) + return -1; + + ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK); + memcpy(ih, (void *)pa->pa_bridgeih[swizpin - 1], + sizeof(struct acpipci_intr_handle)); + *ihp = (pci_intr_handle_t)ih; + + return 0; +} + int acpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) { struct acpipci_softc *sc = pa->pa_pc->pc_intr_v; - struct aml_node *node; + struct aml_node *node = sc->sc_node; struct aml_value res; uint64_t addr, pin, source, index; struct acpipci_intr_handle *ih; int i; - if (pa->pa_bridgetag == NULL) - return -1; - - node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag); - if (node == NULL) - return -1; + /* + * If we're behind a bridge, we need to look for a _PRT for + * it. If we don't find a _PRT, we need to swizzle. If we're + * not behind a bridge we need to look for a _PRT on the host + * bridge node itself. + */ + if (pa->pa_bridgetag) { + node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag); + if (node == NULL) + return acpipci_intr_swizzle(pa, ihp); + } if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res)) - return -1; + return acpipci_intr_swizzle(pa, ihp); if (res.type != AML_OBJTYPE_PACKAGE) return -1; -- 2.20.1