diff options
| author | Ruslan Bukin <br@FreeBSD.org> | 2019-05-08 15:22:27 +0000 |
|---|---|---|
| committer | Ruslan Bukin <br@FreeBSD.org> | 2019-05-08 15:22:27 +0000 |
| commit | 101869a8f0e8e2546a8d0ffeaa93430a3a851216 (patch) | |
| tree | c0c0977462678cfd8bc39370dff1fe85205adfdb /sys/dev/xdma/xdma.c | |
| parent | 9c8f66cb8b4fee9cd5e24a222e5038b838ea73f1 (diff) | |
Notes
Diffstat (limited to 'sys/dev/xdma/xdma.c')
| -rw-r--r-- | sys/dev/xdma/xdma.c | 127 |
1 files changed, 109 insertions, 18 deletions
diff --git a/sys/dev/xdma/xdma.c b/sys/dev/xdma/xdma.c index 3e0a0f05f704..68aac5d5b7c8 100644 --- a/sys/dev/xdma/xdma.c +++ b/sys/dev/xdma/xdma.c @@ -1,6 +1,7 @@ /*- - * Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com> - * All rights reserved. + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2016-2019 Ruslan Bukin <br@bsdpad.com> * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 @@ -43,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/sysctl.h> #include <sys/systm.h> -#include <sys/sx.h> #include <machine/bus.h> @@ -61,11 +61,13 @@ __FBSDID("$FreeBSD$"); * Multiple xDMA controllers may work with single DMA device, * so we have global lock for physical channel management. */ -static struct sx xdma_sx; +static struct mtx xdma_mtx; + +#define XDMA_LOCK() mtx_lock(&xdma_mtx) +#define XDMA_UNLOCK() mtx_unlock(&xdma_mtx) +#define XDMA_ASSERT_LOCKED() mtx_assert(&xdma_mtx, MA_OWNED) -#define XDMA_LOCK() sx_xlock(&xdma_sx) -#define XDMA_UNLOCK() sx_xunlock(&xdma_sx) -#define XDMA_ASSERT_LOCKED() sx_xassert(&xdma_sx, MA_OWNED) +#define FDT_REG_CELLS 4 /* * Allocate virtual xDMA channel. @@ -95,11 +97,11 @@ xdma_channel_alloc(xdma_controller_t *xdma, uint32_t caps) TAILQ_INIT(&xchan->ie_handlers); - sx_init(&xchan->sx_lock, "xDMA chan"); - sx_init(&xchan->sx_qin_lock, "xDMA qin"); - sx_init(&xchan->sx_qout_lock, "xDMA qout"); - sx_init(&xchan->sx_bank_lock, "xDMA bank"); - sx_init(&xchan->sx_proc_lock, "xDMA proc"); + mtx_init(&xchan->mtx_lock, "xDMA chan", NULL, MTX_DEF); + mtx_init(&xchan->mtx_qin_lock, "xDMA qin", NULL, MTX_DEF); + mtx_init(&xchan->mtx_qout_lock, "xDMA qout", NULL, MTX_DEF); + mtx_init(&xchan->mtx_bank_lock, "xDMA bank", NULL, MTX_DEF); + mtx_init(&xchan->mtx_proc_lock, "xDMA proc", NULL, MTX_DEF); TAILQ_INIT(&xchan->bank); TAILQ_INIT(&xchan->queue_in); @@ -138,11 +140,11 @@ xdma_channel_free(xdma_channel_t *xchan) xdma_teardown_all_intr(xchan); - sx_destroy(&xchan->sx_lock); - sx_destroy(&xchan->sx_qin_lock); - sx_destroy(&xchan->sx_qout_lock); - sx_destroy(&xchan->sx_bank_lock); - sx_destroy(&xchan->sx_proc_lock); + mtx_destroy(&xchan->mtx_lock); + mtx_destroy(&xchan->mtx_qin_lock); + mtx_destroy(&xchan->mtx_qout_lock); + mtx_destroy(&xchan->mtx_bank_lock); + mtx_destroy(&xchan->mtx_proc_lock); TAILQ_REMOVE(&xdma->channels, xchan, xchan_next); @@ -303,6 +305,95 @@ xdma_ofw_md_data(xdma_controller_t *xdma, pcell_t *cells, int ncells) return (ret); } +static int +xdma_handle_mem_node(vmem_t *vmem, phandle_t memory) +{ + pcell_t reg[FDT_REG_CELLS * FDT_MEM_REGIONS]; + pcell_t *regp; + int addr_cells, size_cells; + int i, reg_len, ret, tuple_size, tuples; + vmem_addr_t mem_start; + vmem_size_t mem_size; + + if ((ret = fdt_addrsize_cells(OF_parent(memory), &addr_cells, + &size_cells)) != 0) + return (ret); + + if (addr_cells > 2) + return (ERANGE); + + tuple_size = sizeof(pcell_t) * (addr_cells + size_cells); + reg_len = OF_getproplen(memory, "reg"); + if (reg_len <= 0 || reg_len > sizeof(reg)) + return (ERANGE); + + if (OF_getprop(memory, "reg", reg, reg_len) <= 0) + return (ENXIO); + + tuples = reg_len / tuple_size; + regp = (pcell_t *)® + for (i = 0; i < tuples; i++) { + ret = fdt_data_to_res(regp, addr_cells, size_cells, + &mem_start, &mem_size); + if (ret != 0) + return (ret); + + vmem_add(vmem, mem_start, mem_size, 0); + regp += addr_cells + size_cells; + } + + return (0); +} + +vmem_t * +xdma_get_memory(device_t dev) +{ + phandle_t mem_node, node; + pcell_t mem_handle; + vmem_t *vmem; + + node = ofw_bus_get_node(dev); + if (node <= 0) { + device_printf(dev, + "%s called on not ofw based device.\n", __func__); + return (NULL); + } + + if (!OF_hasprop(node, "memory-region")) + return (NULL); + + if (OF_getencprop(node, "memory-region", (void *)&mem_handle, + sizeof(mem_handle)) <= 0) + return (NULL); + + vmem = vmem_create("xDMA vmem", 0, 0, PAGE_SIZE, + PAGE_SIZE, M_BESTFIT | M_WAITOK); + if (vmem == NULL) + return (NULL); + + mem_node = OF_node_from_xref(mem_handle); + if (xdma_handle_mem_node(vmem, mem_node) != 0) { + vmem_destroy(vmem); + return (NULL); + } + + return (vmem); +} + +void +xdma_put_memory(vmem_t *vmem) +{ + + vmem_destroy(vmem); +} + +void +xchan_set_memory(xdma_channel_t *xchan, vmem_t *vmem) +{ + + xchan->vmem = vmem; +} + /* * Allocate xdma controller. */ @@ -400,7 +491,7 @@ static void xdma_init(void) { - sx_init(&xdma_sx, "xDMA"); + mtx_init(&xdma_mtx, "xDMA", NULL, MTX_DEF); } SYSINIT(xdma, SI_SUB_DRIVERS, SI_ORDER_FIRST, xdma_init, NULL); |
