[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