aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xdma/xdma.c
diff options
context:
space:
mode:
authorRuslan Bukin <br@FreeBSD.org>2019-05-08 15:22:27 +0000
committerRuslan Bukin <br@FreeBSD.org>2019-05-08 15:22:27 +0000
commit101869a8f0e8e2546a8d0ffeaa93430a3a851216 (patch)
treec0c0977462678cfd8bc39370dff1fe85205adfdb /sys/dev/xdma/xdma.c
parent9c8f66cb8b4fee9cd5e24a222e5038b838ea73f1 (diff)
Notes
Diffstat (limited to 'sys/dev/xdma/xdma.c')
-rw-r--r--sys/dev/xdma/xdma.c127
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 *)&reg;
+ 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);