Thread (339 messages) 339 messages, 17 authors, 2021-10-17

Re: [dpdk-dev] [PATCH v25 1/6] dmadev: introduce DMA device library

From: Thomas Monjalon <hidden>
Date: 2021-10-12 19:09:49

11/10/2021 09:33, Chengwen Feng:
quoted hunk ↗ jump to hunk
--- /dev/null
+++ b/doc/guides/prog_guide/dmadev.rst
@@ -0,0 +1,60 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+   Copyright 2021 HiSilicon Limited
+
+DMA Device Library
+==================
+
+The DMA library provides a DMA device framework for management and provisioning
+of hardware and software DMA poll mode drivers, defining generic API which
+support a number of different DMA operations.
+
+
+Design Principles
+-----------------
+
+The DMA framework provides a generic DMA device framework which supports both
+physical (hardware) and virtual (software) DMA devices, as well as a generic DMA
+API which allows DMA devices to be managed and configured, and supports DMA
+operations to be provisioned on DMA poll mode driver.
+
+.. _figure_dmadev:
+
+.. figure:: img/dmadev.*
+
+The above figure shows the model on which the DMA framework is built on:
+
+ * The DMA controller could have multiple hardware DMA channels (aka. hardware
+   DMA queues), each hardware DMA channel should be represented by a dmadev.
+ * The dmadev could create multiple virtual DMA channels, each virtual DMA
+   channel represents a different transfer context. The DMA operation request
+   must be submitted to the virtual DMA channel. e.g. Application could create
+   virtual DMA channel 0 for memory-to-memory transfer scenario, and create
+   virtual DMA channel 1 for memory-to-device transfer scenario.
When updating the doc, we would like to change a minimum of lines,
so it's better to split lines logically: after a comma, a point,
or before the next part of the sentence.
Do not hesitate to make short lines if needed.
Such change is quite fast to do, thanks.

[...]
+* **Introduced dmadev library with:**
+
+  * Device allocation functions.
You can drop this line, it is not a feature.

[...]
+static int
+dma_dev_data_prepare(void)
+{
+	size_t size;
+
+	if (rte_dma_devices != NULL)
+		return 0;
+
+	size = dma_devices_max * sizeof(struct rte_dma_dev);
+	rte_dma_devices = malloc(size);
+	if (rte_dma_devices == NULL)
+		return -ENOMEM;
+	memset(rte_dma_devices, 0, size);
+
+	return 0;
+}
+
+static int
+dma_data_prepare(void)
+{
+	if (dma_devices_max == 0)
+		dma_devices_max = RTE_DMADEV_DEFAULT_MAX;
+	return dma_dev_data_prepare();
+}
+
+static struct rte_dma_dev *
+dma_allocate(const char *name, int numa_node, size_t private_data_size)
+{
+	struct rte_dma_dev *dev;
+	void *dev_private;
+	int16_t dev_id;
+	int ret;
+
+	ret = dma_data_prepare();
+	if (ret < 0) {
+		RTE_DMA_LOG(ERR, "Cannot initialize dmadevs data");
+		return NULL;
+	}
+
+	dev = dma_find_by_name(name);
+	if (dev != NULL) {
+		RTE_DMA_LOG(ERR, "DMA device already allocated");
+		return NULL;
+	}
+
+	dev_private = rte_zmalloc_socket(name, private_data_size,
+					 RTE_CACHE_LINE_SIZE, numa_node);
+	if (dev_private == NULL) {
+		RTE_DMA_LOG(ERR, "Cannot allocate private data");
+		return NULL;
+	}
+
+	dev_id = dma_find_free_id();
+	if (dev_id < 0) {
+		RTE_DMA_LOG(ERR, "Reached maximum number of DMA devices");
+		rte_free(dev_private);
+		return NULL;
+	}
+
+	dev = &rte_dma_devices[dev_id];
+	rte_strscpy(dev->dev_name, name, sizeof(dev->dev_name));
+	dev->dev_id = dev_id;
+	dev->numa_node = numa_node;
+	dev->dev_private = dev_private;
+
+	return dev;
+}
+
+static void
+dma_release(struct rte_dma_dev *dev)
+{
+	rte_free(dev->dev_private);
+	memset(dev, 0, sizeof(struct rte_dma_dev));
+}
+
+struct rte_dma_dev *
+rte_dma_pmd_allocate(const char *name, int numa_node, size_t private_data_size)
+{
+	struct rte_dma_dev *dev;
+
+	if (dma_check_name(name) != 0 || private_data_size == 0)
+		return NULL;
+
+	dev = dma_allocate(name, numa_node, private_data_size);
+	if (dev == NULL)
+		return NULL;
+
+	dev->state = RTE_DMA_DEV_REGISTERED;
+
+	return dev;
+}
+
+int
+rte_dma_pmd_release(const char *name)
+{
+	struct rte_dma_dev *dev;
+
+	if (dma_check_name(name) != 0)
+		return -EINVAL;
+
+	dev = dma_find_by_name(name);
+	if (dev == NULL)
+		return -EINVAL;
+
+	dma_release(dev);
+	return 0;
+}
Trying to understand the logic of creation/destroy.
skeldma_probe
\-> skeldma_create
    \-> rte_dma_pmd_allocate
        \-> dma_allocate
            \-> dma_data_prepare
                \-> dma_dev_data_prepare
skeldma_remove
\-> skeldma_destroy
    \-> rte_dma_pmd_release
        \-> dma_release
app
\-> rte_dma_close
    \-> skeldma_close
    \-> dma_release

My only concern is that the PMD remove does not call rte_dma_close.
The PMD should check which dmadev is open for the rte_device to remove,
and close the dmadev first.
This way, no need for the function rte_dma_pmd_release,
and no need to duplicate the release process in two paths.
By the way, the function vchan_release is called only in the close function,
not in the "remove path".


Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help