From c1448d3e66e91ca68512febe40ad5b32c5b72cfa Mon Sep 17 00:00:00 2001 From: jmcneill Date: Tue, 31 Dec 2019 11:42:46 +0000 Subject: [PATCH] The DMA restrictions may not be defined in the direct parent of a device, so search up the tree for a module device. --- sys/arch/arm/acpi/acpi_machdep.c | 37 +++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/sys/arch/arm/acpi/acpi_machdep.c b/sys/arch/arm/acpi/acpi_machdep.c index 53b95c8390e7..2f26d46a17dc 100644 --- a/sys/arch/arm/acpi/acpi_machdep.c +++ b/sys/arch/arm/acpi/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.c,v 1.15 2019/12/30 19:50:29 jmcneill Exp $ */ +/* $NetBSD: acpi_machdep.c,v 1.16 2019/12/31 11:42:46 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #include "pci.h" #include -__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.15 2019/12/30 19:50:29 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.16 2019/12/31 11:42:46 jmcneill Exp $"); #include #include @@ -410,9 +410,32 @@ done: return dmat; } +static ACPI_HANDLE +arm_acpi_dma_module(struct acpi_softc *sc, struct acpi_devnode *ad) +{ + ACPI_HANDLE tmp; + ACPI_STATUS rv; + + /* + * Search up the tree for a module device with a _DMA method. + */ + for (; ad != NULL; ad = ad->ad_parent) { + if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE) + continue; + if (!acpi_match_hid(ad->ad_devinfo, module_hid)) + continue; + rv = AcpiGetHandle(ad->ad_handle, "_DMA", &tmp); + if (ACPI_SUCCESS(rv)) + return ad->ad_handle; + } + + return NULL; +} + bus_dma_tag_t arm_acpi_dma_tag(struct acpi_softc *sc, struct acpi_devnode *ad) { + ACPI_HANDLE module; ACPI_INTEGER cca; bus_dma_tag_t dmat; @@ -425,14 +448,12 @@ arm_acpi_dma_tag(struct acpi_softc *sc, struct acpi_devnode *ad) dmat = &arm_generic_dma_tag; /* - * If the parent device is a bus, it may define valid DMA ranges + * If a parent device is a bus, it may define valid DMA ranges * and translations for child nodes. */ - if (ad->ad_parent != NULL && - acpi_match_hid(ad->ad_parent->ad_devinfo, module_hid)) { - dmat = arm_acpi_dma_tag_subregion(sc, dmat, - ad->ad_parent->ad_handle); - } + module = arm_acpi_dma_module(sc, ad); + if (module != NULL) + dmat = arm_acpi_dma_tag_subregion(sc, dmat, module); return dmat; }