Page MenuHomeFreeBSD

D25316.diff
No OneTemporary

D25316.diff

Index: sys/dev/dmaengine/dmaengine.h
===================================================================
--- /dev/null
+++ sys/dev/dmaengine/dmaengine.h
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (C) 2020 Advanced Micro Devices, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of AMD corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Contact Information :
+ * Rajesh Kumar <rajesh1.kumar@amd.com>
+ *
+ */
+
+#ifndef _DMAENGINE_H_
+#define _DMAENGINE_H_
+
+#include "dmaengine_if.h"
+
+extern devclass_t dmaengine_hw_devclass;
+SYSCTL_DECL(_hw_dmaengine);
+
+int dmaengine_register_device(device_t);
+int dmaengine_unregister_device(device_t);
+int dmaengine_child_location_str(device_t, device_t, char *, size_t);
+int dmaengine_print_child(device_t, device_t);
+
+/*
+ * dmaengine_get_chan_idx() - get the index of an available dma channel from
+ * the dmaengine
+ * @chan_cnt: Total number of dma channels needed
+ *
+ * Test applications can obtain the index of the available dma channel from
+ * the dmaengine based on the total number of dma channels needed.
+ */
+int dmaengine_get_chan_idx(ssize_t chan_cnt);
+
+/*
+ * dmaengine_get_channel() - get the reference of the pointed dma channel from
+ * the dmaengine
+ * @chan_idx: Index of the channel to get reference
+ * @flags: Additional optional params
+ *
+ * Test applications can obtain the reference of the pointed dma channel from
+ * the dmaengine.
+ */
+bus_dmaengine_t dmaengine_get_channel(uint32_t chan_idx, int flags);
+
+/*
+ * dmaengine_put_channel() - free the reference of the pointed dma channel from
+ * the dmaengine
+ * @channel: Reference of the channel to be freed.
+ *
+ * Test applications can free the reference of the pointed dma channel from
+ * the dmaengine.
+ */
+void dmaengine_put_channel(bus_dmaengine_t dmaengine);
+
+/* dmaengine_copy() - copy from source to destination using the specified
+ * dmaengine.
+ * @dmaengine: DMA engine to use for copy
+ * @dst: Destination address
+ * @src: Source address
+ * @len: Length of the data to be copied
+ * @callback_fn: Callback funtion to notify copy completion
+ * @callback_arg: Argument to be passed to @callback_fn
+ * @flags: Additional optional params
+ */
+int dmaengine_copy(bus_dmaengine_t dmaengine, bus_addr_t dst, bus_addr_t src,
+ bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg,
+ uint32_t flags);
+
+#endif /* _DMAENGINE_H_ */
Index: sys/dev/dmaengine/dmaengine.c
===================================================================
--- /dev/null
+++ sys/dev/dmaengine/dmaengine.c
@@ -0,0 +1,274 @@
+/*-
+ * Copyright (C) 2020 Advanced Micro Devices, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of AMD corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Contact Information :
+ * Rajesh Kumar <rajesh1.kumar@amd.com>
+ *
+ */
+
+/*
+ * This is a generic interface driver for any DMA ENGINE devices. This can
+ * be used by any test applications or drivers to request and release DMA
+ * channels, and to initiate the DMA operations without the knowledge of the
+ * underlying vendor specific DMA hardware.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rmlock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+
+#include "dmaengine.h"
+
+devclass_t dmaengine_hw_devclass;
+
+struct dmaengine_child {
+
+ TAILQ_ENTRY(dmaengine_child) entry;
+
+ device_t dmadev;
+ device_t parent;
+ int function;
+ int chan_idx;
+ int refcnt;
+ bus_dmaengine_t dmaengine;
+ struct dmaengine_child *next;
+};
+
+struct mtx dma_channel_lock;
+
+/* List of registered DMA channels */
+TAILQ_HEAD(dma_channel, dmaengine_child) dma_channel;
+
+SYSCTL_NODE(_hw, OID_AUTO, dmaengine, CTLFLAG_RW, 0, "DMA engine sysctls");
+
+static unsigned dma_channel_idx = 0;
+SYSCTL_UINT(_hw_dmaengine, OID_AUTO, channels, CTLFLAG_RD, &dma_channel_idx, 0,
+ "Number of DMA channels registered");
+
+/*
+ * Register a DMA channel
+ *
+ */
+int
+dmaengine_register_device(device_t dmadev)
+{
+ struct dmaengine_child **cpp = device_get_softc(dmadev);
+ struct dmaengine_child *dc;
+
+ device_printf(dmadev, "Registering DMA Engine\n");
+
+ if (dma_channel.tqh_last == NULL) {
+ mtx_init(&dma_channel_lock, "DMA Channel list lock", 0, MTX_DEF);
+ TAILQ_INIT(&dma_channel);
+ }
+
+ mtx_lock(&dma_channel_lock);
+
+ dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK | M_ZERO);
+ if (dc == NULL)
+ return (ENOMEM);
+
+ dc->function = 0;
+ dc->chan_idx = dma_channel_idx;
+ dc->refcnt = 0;
+ dc->parent = dmadev;
+ dc->dmadev = device_add_child(dmadev, NULL, -1);
+ if (dc->dmadev == NULL) {
+ free(dc, M_DEVBUF);
+ return (ENOMEM);
+ }
+ device_set_ivars(dc->dmadev, dc);
+ *cpp = dc;
+ dma_channel_idx++;
+
+ TAILQ_INSERT_TAIL(&dma_channel, dc, entry);
+
+ mtx_unlock(&dma_channel_lock);
+
+ bus_generic_attach(dmadev);
+ return (0);
+}
+
+/*
+ * UnRegister a DMA channel
+ *
+ */
+int
+dmaengine_unregister_device(device_t dmadev)
+{
+ struct dmaengine_child **cpp = device_get_softc(dmadev);
+ struct dmaengine_child *dc = *cpp;
+ int error = 0;
+
+ device_printf(dmadev, "Registering DMA Engine\n");
+
+ mtx_lock(&dma_channel_lock);
+
+ TAILQ_REMOVE(&dma_channel, dc, entry);
+
+ error = device_delete_child(dmadev, dc->dmadev);
+ if (error)
+ goto out;
+
+ free(dc, M_DEVBUF);
+ dma_channel_idx--;
+
+ mtx_unlock(&dma_channel_lock);
+out:
+
+ return (0);
+}
+
+int
+dmaengine_child_location_str(device_t dmadev, device_t child, char *buf,
+ size_t buflen)
+{
+ struct dmaengine_child *dc = device_get_ivars(child);
+
+ snprintf(buf, buflen, "function=%d", dc->function);
+ return (0);
+}
+
+int
+dmaengine_print_child(device_t dmadev, device_t child)
+{
+ struct dmaengine_child *dc = device_get_ivars(child);
+ int retval;
+
+ retval = bus_print_child_header(dmadev, child);
+ retval += printf(" at function %d", dc->function);
+ retval += bus_print_child_domain(dmadev, child);
+ retval += bus_print_child_footer(dmadev, child);
+
+ return (retval);
+}
+
+/*
+ * Get a reference to the child of a registered DMA channel
+ *
+ */
+static struct dmaengine_child *
+dmaengine_get_dc(int chan_idx, bus_dmaengine_t dmaengine, int tcnt)
+{
+ struct dmaengine_child *dc = NULL, *dc_tmp = NULL;
+
+ mtx_lock(&dma_channel_lock);
+
+ TAILQ_FOREACH_SAFE(dc, &dma_channel, entry, dc_tmp) {
+ if (chan_idx >= 0) {
+ if (dc->chan_idx == chan_idx)
+ break;
+ }
+
+ if (dmaengine != NULL) {
+ if (dc->dmaengine == dmaengine)
+ break;
+ }
+
+ if (tcnt > 0) {
+ if (dc->refcnt == 0) {
+ atomic_add_int(&dc->refcnt, 1);
+ break;
+ }
+ }
+ }
+
+ mtx_unlock(&dma_channel_lock);
+
+ return (dc);
+}
+
+/*
+ * Get the index of a DMA channel to be used
+ *
+ */
+int
+dmaengine_get_chan_idx(ssize_t tcnt)
+{
+ struct dmaengine_child *dc;
+
+ dc = dmaengine_get_dc(-1, NULL, tcnt);
+
+ return (dc->chan_idx);
+}
+
+/*
+ * Take a reference to the DMA channel of the specified index
+ *
+ */
+bus_dmaengine_t
+dmaengine_get_channel(uint32_t chan_idx, int flags)
+{
+ struct dmaengine_child *dc;
+
+ dc = dmaengine_get_dc(chan_idx, NULL, 0);
+ dc->dmaengine = DMAENGINE_GET_CHANNEL(dc->parent, chan_idx, flags);
+
+ return (dc->dmaengine);
+}
+
+/*
+ * Free the reference of the specified DMA channel
+ *
+ */
+void
+dmaengine_put_channel(bus_dmaengine_t dmaengine)
+{
+ struct dmaengine_child *dc;
+
+ dc = dmaengine_get_dc(-1, dmaengine, 0);
+ dc->dmaengine = NULL;
+ DMAENGINE_PUT_CHANNEL(dc->parent, dmaengine);
+}
+
+/*
+ * Initiate a DMA copy on the specified DMA channel with the specified
+ * parameters along with a callback function to notify the completion.
+ *
+ */
+int
+dmaengine_copy(bus_dmaengine_t dmaengine, bus_addr_t dst,
+ bus_addr_t src, bus_size_t len, bus_dmaengine_callback_t callback_fn,
+ void *callback_arg, uint32_t flags)
+{
+ struct dmaengine_child *dc;
+
+ dc = dmaengine_get_dc(-1, dmaengine, 0);
+ return DMAENGINE_COPY(dc->parent, dmaengine, dst, src, len, callback_fn,
+ callback_arg, flags);
+}
+
+MODULE_VERSION(dmaengine, 1);
Index: sys/dev/dmaengine/dmaengine_if.m
===================================================================
--- /dev/null
+++ sys/dev/dmaengine/dmaengine_if.m
@@ -0,0 +1,69 @@
+#-
+# Copyright (C) 2020 Advanced Micro Devices, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of AMD corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# Contact Information :
+# Rajesh Kumar <rajesh1.kumar@amd.com>
+#
+# $FreeBSD$
+#
+
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+INTERFACE dmaengine;
+
+HEADER {
+ typedef void *bus_dmaengine_t;
+ typedef void (*bus_dmaengine_callback_t)(void *arg, int error);
+};
+
+METHOD int get_chan_idx {
+ device_t dmadev;
+ ssize_t chan_cnt;
+};
+
+METHOD bus_dmaengine_t get_channel {
+ device_t dmadev;
+ uint32_t chan_idx;
+ int flags;
+};
+
+METHOD void put_channel {
+ device_t dmadev;
+ bus_dmaengine_t dmaengine;
+};
+
+METHOD int copy {
+ device_t dmadev;
+ bus_dmaengine_t dmaengine;
+ bus_addr_t dst;
+ bus_addr_t src;
+ bus_size_t len;
+ bus_dmaengine_callback_t callback_fn;
+ void *callback_arg;
+ uint32_t flags;
+};
Index: sys/modules/dmaengine/Makefile
===================================================================
--- /dev/null
+++ sys/modules/dmaengine/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= dmaengine
+
+.include <bsd.subdir.mk>
Index: sys/modules/dmaengine/dmaengine/Makefile
===================================================================
--- /dev/null
+++ sys/modules/dmaengine/dmaengine/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/dev/dmaengine
+
+KMOD = dmaengine
+SRCS = dmaengine.c dmaengine_if.c
+SRCS += device_if.h bus_if.h dmaengine_if.h
+
+.include <bsd.kmod.mk>

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 27, 10:20 AM (11 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37335443
Default Alt Text
D25316.diff (13 KB)

Event Timeline