[dpdk-dev] [PATCH v1 22/28] eal/soc: detect DMA non-coherent devices

Jan Viktorin viktorin at rehivetech.com
Fri May 6 15:48:04 CEST 2016


The SoC devices can be sometimes DMA non-coherent. This means that we need
to take care of memory allocation for those. Generally, drivers assume that
every device is DMA coherent. If a driver supports a DMA non-coherent device,
it sets the RTE_SOC_DRV_ACCEPT_NONCC flag.

Note that the is_dma_coherent flag have in fact the following semantics:

 * if true the device is DMA coherent
 * otherwise we don't know...

Notes:

The current dma-coherent detection is not perfect as the property may be placed
in parent nodes of FDT as well. It is a question whether this detection is
important here because the kernel drivers might help transparently. However,
at the moment, there is no standard kernel driver that provides the proper
memory (dma_alloc_coherent) to us. So we can either create one or patch the
uio_dmem_genirq to be more generic (this is a way to go). Anyway, a custom
mempool should be used here.

Signed-off-by: Jan Viktorin <viktorin at rehivetech.com>
---
 lib/librte_eal/common/eal_common_soc.c  |  8 ++++++++
 lib/librte_eal/common/include/rte_soc.h |  3 +++
 lib/librte_eal/linuxapp/eal/eal_soc.c   | 24 ++++++++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 49dbcb8..4d32826 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -120,6 +120,14 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
 		return 1;
 	}
 
+	if (!dev->is_dma_coherent) {
+		if (!(dr->drv_flags & RTE_SOC_DRV_ACCEPT_NONCC)) {
+			RTE_LOG(DEBUG, EAL,
+				"  device is not DMA coherent, skipping\n");
+			return 1;
+		}
+	}
+
 	if (dr->drv_flags & RTE_SOC_DRV_NEED_MAPPING) {
 		/* map resources */
 		ret = rte_eal_soc_map_device(dev);
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 50a3b35..2225a63 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -100,6 +100,7 @@ struct rte_soc_device {
 	struct rte_intr_handle intr_handle; /**< Interrupt handle */
 	struct rte_soc_driver *driver;      /**< Associated driver */
 	int numa_node;                      /**< NUMA node connection */
+	int is_dma_coherent;                /**< DMA coherent device */
 	struct rte_devargs *devargs;        /**< Device user arguments */
 	enum rte_kernel_driver kdrv;        /**< Kernel driver */
 };
@@ -136,6 +137,8 @@ struct rte_soc_driver {
 #define RTE_SOC_DRV_INTR_LSC	 0x0008
 /** Device driver supports detaching capability */
 #define RTE_SOC_DRV_DETACHABLE	 0x0010
+/** Device driver accepts DMA non-coherent devices */
+#define RTE_SOC_DRV_ACCEPT_NONCC 0x0020
 
 /**
  * A structure describing a SoC mapping.
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 6e9e242..5277fb7 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -328,6 +328,25 @@ dev_setup_numa_node(struct rte_soc_device *dev, const char *dirname)
 	return ret;
 }
 
+static int
+dev_detect_is_coherent(struct rte_soc_device *dev)
+{
+	char filename[PATH_MAX];
+	FILE *f;
+
+	if (dev->addr.fdt_path == NULL)
+		return 0; /* no way to detect */
+
+	snprintf(filename, sizeof(filename), "%s%s/dma-coherent",
+			"/proc/device-tree", dev->addr.fdt_path);
+	if ((f = fopen(filename, "r")) == NULL) {
+		return 0;
+	}
+
+	fclose(f);
+	return 1;
+}
+
 /**
  * Scan one SoC sysfs entry, and fill the devices list from it.
  * We require to have the uevent file with records: OF_FULLNAME and
@@ -372,6 +391,10 @@ soc_scan_one(const char *dirname, const char *name)
 	if ((ret = dev_setup_numa_node(dev, dirname)) < 0)
 		goto fail;
 
+	dev->is_dma_coherent = dev_detect_is_coherent(dev);
+	RTE_LOG(DEBUG, EAL, "  DMA %s\n",
+			dev->is_dma_coherent? "coherent" : "non-coherent");
+
 	/* device is valid, add in list (sorted) */
 	if (TAILQ_EMPTY(&soc_device_list)) {
 		TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
@@ -387,6 +410,7 @@ soc_scan_one(const char *dirname, const char *name)
 				TAILQ_INSERT_BEFORE(dev2, dev, next);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
+				dev2->is_dma_coherent = dev->is_dma_coherent;
 				memmove(dev2->mem_resource, dev->mem_resource,
 					sizeof(dev->mem_resource));
 
-- 
2.8.0



More information about the dev mailing list