Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/acpi Create bus_dma tags for each device node b...
details: https://anonhg.NetBSD.org/src/rev/9c153ba8edda
branches: trunk
changeset: 968007:9c153ba8edda
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Dec 31 13:54:22 2019 +0000
description:
Create bus_dma tags for each device node based on _CCA and _DMA properties
found by walking up the device node tree. These tags encode range
restrictions, address translations, and whether or not the device is
cache coherent.
diffstat:
sys/arch/arm/acpi/acpi_machdep.c | 150 ++++++++++++++++++++++++--------------
1 files changed, 93 insertions(+), 57 deletions(-)
diffs (189 lines):
diff -r 71d983fa37d5 -r 9c153ba8edda sys/arch/arm/acpi/acpi_machdep.c
--- a/sys/arch/arm/acpi/acpi_machdep.c Tue Dec 31 13:39:15 2019 +0000
+++ b/sys/arch/arm/acpi/acpi_machdep.c Tue Dec 31 13:54:22 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_machdep.c,v 1.16 2019/12/31 11:42:46 jmcneill Exp $ */
+/* $NetBSD: acpi_machdep.c,v 1.17 2019/12/31 13:54:22 jmcneill Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,13 +32,14 @@
#include "pci.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.16 2019/12/31 11:42:46 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.17 2019/12/31 13:54:22 jmcneill Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
+#include <sys/kmem.h>
#include <uvm/uvm_extern.h>
@@ -372,44 +373,6 @@
NULL
};
-static bus_dma_tag_t
-arm_acpi_dma_tag_subregion(struct acpi_softc *sc, bus_dma_tag_t dmat,
- ACPI_HANDLE handle)
-{
- struct acpi_resources res;
- struct acpi_mem *mem;
- bus_dma_tag_t newtag;
- ACPI_STATUS rv;
- int error;
-
- rv = acpi_resource_parse(sc->sc_dev, handle, "_DMA", &res,
- &acpi_resource_parse_ops_quiet);
- if (ACPI_FAILURE(rv))
- return dmat; /* no translation required */
-
- mem = acpi_res_mem(&res, 0);
- if (mem == NULL)
- goto done;
-
- aprint_debug_dev(sc->sc_dev, "_DMA range %#lx-%#lx\n",
- mem->ar_base, mem->ar_base + mem->ar_length - 1);
-
- error = bus_dmatag_subregion(dmat,
- mem->ar_base, mem->ar_base + mem->ar_length - 1,
- &newtag, BUS_DMA_WAITOK);
- if (error != 0) {
- aprint_error_dev(sc->sc_dev,
- "_DMA subregion failed: %d\n", error);
- goto done;
- }
- dmat = newtag;
-
-done:
- acpi_resource_cleanup(&res);
-
- return dmat;
-}
-
static ACPI_HANDLE
arm_acpi_dma_module(struct acpi_softc *sc, struct acpi_devnode *ad)
{
@@ -432,28 +395,101 @@
return NULL;
}
+static void
+arm_acpi_dma_init_ranges(struct acpi_softc *sc, struct acpi_devnode *ad,
+ struct arm32_bus_dma_tag *dmat, uint32_t flags)
+{
+ struct acpi_resources res;
+ struct acpi_mem *mem;
+ ACPI_HANDLE module;
+ ACPI_STATUS rv;
+ int n;
+
+ module = arm_acpi_dma_module(sc, ad->ad_parent);
+ if (module == NULL) {
+default_tag:
+ /* No translation required */
+ dmat->_nranges = 1;
+ dmat->_ranges = kmem_zalloc(sizeof(*dmat->_ranges), KM_SLEEP);
+ dmat->_ranges[0].dr_sysbase = 0;
+ dmat->_ranges[0].dr_busbase = 0;
+ dmat->_ranges[0].dr_len = UINTPTR_MAX;
+ dmat->_ranges[0].dr_flags = flags;
+ return;
+ }
+
+ rv = acpi_resource_parse(sc->sc_dev, module, "_DMA", &res,
+ &acpi_resource_parse_ops_quiet);
+ if (ACPI_FAILURE(rv)) {
+ aprint_error_dev(sc->sc_dev,
+ "failed to parse _DMA on %s: %s\n",
+ acpi_name(module), AcpiFormatException(rv));
+ goto default_tag;
+ }
+ if (res.ar_nmem == 0) {
+ acpi_resource_cleanup(&res);
+ goto default_tag;
+ }
+
+ dmat->_nranges = res.ar_nmem;
+ dmat->_ranges = kmem_zalloc(sizeof(*dmat->_ranges) * res.ar_nmem,
+ KM_SLEEP);
+
+ for (n = 0; n < res.ar_nmem; n++) {
+ mem = acpi_res_mem(&res, n);
+ dmat->_ranges[n].dr_busbase = mem->ar_base;
+ dmat->_ranges[n].dr_sysbase = mem->ar_base;
+ if (mem->ar_decode == ACPI_POS_DECODE)
+ dmat->_ranges[n].dr_sysbase += mem->ar_offset;
+ else
+ dmat->_ranges[n].dr_sysbase -= mem->ar_offset;
+ dmat->_ranges[n].dr_len = mem->ar_length;
+ dmat->_ranges[n].dr_flags = flags;
+
+ aprint_debug_dev(sc->sc_dev,
+ "%s: DMA sysbase %#lx busbase %#lx len %#lx%s\n",
+ acpi_name(ad->ad_handle),
+ dmat->_ranges[n].dr_sysbase,
+ dmat->_ranges[n].dr_busbase,
+ dmat->_ranges[n].dr_len,
+ flags ? " (coherent)" : "");
+ }
+
+ acpi_resource_cleanup(&res);
+}
+
+static uint32_t
+arm_acpi_dma_flags(struct acpi_softc *sc, struct acpi_devnode *ad)
+{
+ ACPI_INTEGER cca = 1; /* default cache coherent */
+ ACPI_STATUS rv;
+
+ for (; ad != NULL; ad = ad->ad_parent) {
+ if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
+ continue;
+
+ rv = acpi_eval_integer(ad->ad_handle, "_CCA", &cca);
+ if (ACPI_SUCCESS(rv))
+ break;
+ }
+
+ return cca ? _BUS_DMAMAP_COHERENT : 0;
+}
+
+
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;
-
- if (ACPI_FAILURE(acpi_eval_integer(ad->ad_handle, "_CCA", &cca)))
- cca = 1;
+ struct arm32_bus_dma_tag *dmat;
- if (cca)
- dmat = &acpi_coherent_dma_tag;
- else
- dmat = &arm_generic_dma_tag;
+ if (ad->ad_dmat != NULL)
+ return ad->ad_dmat;
+
+ dmat = kmem_alloc(sizeof(*dmat), KM_SLEEP);
+ *dmat = arm_generic_dma_tag;
- /*
- * If a parent device is a bus, it may define valid DMA ranges
- * and translations for child nodes.
- */
- module = arm_acpi_dma_module(sc, ad);
- if (module != NULL)
- dmat = arm_acpi_dma_tag_subregion(sc, dmat, module);
+ const uint32_t flags = arm_acpi_dma_flags(sc, ad);
+ arm_acpi_dma_init_ranges(sc, ad, dmat, flags);
return dmat;
}
Home |
Main Index |
Thread Index |
Old Index