[dpdk-dev] [RFC 1/7] eal/common: define rte_soc_* related common interface

Jan Viktorin viktorin at rehivetech.com
Fri Jan 1 22:05:20 CET 2016


Introduce the interface to SoC device infrastructure. A SoC device
here means a device integrated on the chip via a (simple) bus
that lacks of auto-discovery and other properties which are common
for PCI. A counterpart in the Linux Kernel would be a platform_device
(but this is not necessarily 1:1 mapping).

Systems without auto-discovery properties are described by a (Flat)
Device Tree. Device Tree is usually available on embedded systems
in /proc/device-tree. Every device has a unique path in the Device
Tree and so it identifies every such device. This path is used
to identify a device in rte_soc_addr.

Binding of drivers to devices in the Linux Kernel is often done
by matching the compatible entry in the Device Tree. As there is
no standard/generic way to read information like vendor, model, etc.
from each SoC device, we match devices by the compatible entry too.
The rte_soc_id contains an array of compatible strings telling what
each device is compatible with.

There are no DPDK-specific OS drivers for SoC devices at the moment
and unfortunately we cannot use the PCI-related ones as they contain
too much PCI-specific logic.

Whitelisting and blacklisting of devices is based on the Device Tree
identifier (rte_soc_addr) to mimic the PCI behaviour.

Signed-off-by: Jan Viktorin <viktorin at rehivetech.com>
---
 lib/librte_eal/common/Makefile              |   2 +-
 lib/librte_eal/common/eal_common_devargs.c  |   6 +
 lib/librte_eal/common/include/rte_devargs.h |   7 +
 lib/librte_eal/common/include/rte_soc.h     | 210 ++++++++++++++++++++++++++++
 4 files changed, 224 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/include/rte_soc.h

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index f5ea0ee..21326d7 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -33,7 +33,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 
 INC := rte_branch_prediction.h rte_common.h
 INC += rte_debug.h rte_eal.h rte_errno.h rte_launch.h rte_lcore.h
-INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h
+INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h rte_soc.h
 INC += rte_pci_dev_ids.h rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index 5d075d0..201f298 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -105,6 +105,12 @@ rte_eal_devargs_add(enum rte_devtype devtype, const char *devargs_str)
 			goto fail;
 
 		break;
+	case RTE_DEVTYPE_WHITELISTED_SOC:
+	case RTE_DEVTYPE_BLACKLISTED_SOC:
+		strncpy(devargs->soc.addr.devtree_path,
+				buf, PATH_MAX);
+		/* TODO: test file exists? */
+		break;
 	case RTE_DEVTYPE_VIRTUAL:
 		/* save driver name */
 		ret = snprintf(devargs->virt.drv_name,
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 53c59f5..f69a553 100644
--- a/lib/librte_eal/common/include/rte_devargs.h
+++ b/lib/librte_eal/common/include/rte_devargs.h
@@ -51,6 +51,7 @@ extern "C" {
 #include <stdio.h>
 #include <sys/queue.h>
 #include <rte_pci.h>
+#include <rte_soc.h>
 
 /**
  * Type of generic device
@@ -58,6 +59,8 @@ extern "C" {
 enum rte_devtype {
 	RTE_DEVTYPE_WHITELISTED_PCI,
 	RTE_DEVTYPE_BLACKLISTED_PCI,
+	RTE_DEVTYPE_WHITELISTED_SOC,
+	RTE_DEVTYPE_BLACKLISTED_SOC,
 	RTE_DEVTYPE_VIRTUAL,
 };
 
@@ -82,6 +85,10 @@ struct rte_devargs {
 			/** PCI location. */
 			struct rte_pci_addr addr;
 		} pci;
+		struct {
+			/** SoC location. */
+			struct rte_soc_addr addr;
+		} soc;
 		/** Used if type is RTE_DEVTYPE_VIRTUAL. */
 		struct {
 			/** Driver name. */
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
new file mode 100644
index 0000000..7c279b1
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -0,0 +1,210 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 RehiveTech. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Intel 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ *   OWNER 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.
+ */
+
+#ifndef _RTE_SOC_H_
+#define _RTE_SOC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <rte_interrupts.h>
+
+TAILQ_HEAD(soc_device_list, rte_soc_device);
+TAILQ_HEAD(soc_driver_list, rte_soc_driver);
+
+extern struct soc_device_list soc_device_list;
+extern struct soc_driver_list soc_driver_list;
+
+/* Path to detect platform devices (in architecture-specific bus systems). */
+#define SYSFS_SOC_DEVICES "/sys/bus/platform/devices"
+/* Flat Device Tree location in the system. */
+#define FDT_ROOT "/proc/device-tree"
+
+struct rte_soc_resource {
+	uint64_t phys_addr; /**< Physical address, 0 if no resource. */
+	uint64_t len;       /**< Length of the resource. */
+	void *addr;         /**< Virtual address, NULL when not mapped. */
+};
+
+/** Maximum number of SoC resources. */
+#define SOC_MAX_RESOURCE 6
+
+struct rte_soc_id {
+	char **compatible; /**< List of compatible strings. */
+};
+
+struct rte_soc_addr {
+	char devtree_path[PATH_MAX]; /** Path to identify the device in FDT. */
+};
+
+enum rte_soc_kernel_driver {
+	RTE_SOC_KDRV_UNKNOWN = 0,
+	RTE_SOC_KDRV_NONE
+};
+
+/**
+ * A structure describing a SoC device. A SoC device is connected via some
+ * architecture-specific bus without auto-discovery features. Currently, this
+ * covers devices detected by reading the device-tree provided by the OS.
+ */
+struct rte_soc_device {
+	TAILQ_ENTRY(rte_soc_device) next;   /**< Next probed SoC device. */
+	struct rte_soc_addr addr;           /**< Device-tree location. */
+	struct rte_soc_id id;               /**< Device identification. */
+	struct rte_soc_resource mem_resource[SOC_MAX_RESOURCE]; /**< SoC memory resource. */
+	struct rte_intr_handle intr_handle; /**< Interrupt handle. */
+	struct rte_soc_driver *driver;      /**< Associated driver. */
+	int numa_node;                      /**< NUMA node connection. */
+	struct rte_devargs *devargs;        /**< Device user arguments. */
+	enum rte_soc_kernel_driver kdrv;    /**< Kernel driver passthrough. */
+};
+
+struct rte_soc_driver;
+
+/**
+ * Initialization function for the driver called during SoC probing.
+ */
+typedef int (soc_devinit_t)(struct rte_soc_driver *, struct rte_soc_device *);
+
+/**
+ * Uninitialization function for the driver called during SoC hotplugging.
+ */
+typedef int (soc_devuninit_t)(struct rte_soc_device *);
+
+struct rte_soc_driver {
+	TAILQ_ENTRY(rte_soc_driver) next;  /**< Next in list. */
+	const char *name;                  /**< Driver name. */
+	soc_devinit_t *devinit;            /**< Device init. function. */
+	soc_devuninit_t *devuninit;        /**< Device uninit. function. */
+	const struct rte_soc_id *id_table; /**< ID table, NULL terminated. */
+	uint32_t drv_flags;                /**< Flags for handling of device. */
+};
+
+struct soc_map {
+	void *addr;
+	char *path;
+	uint64_t offset;
+	uint64_t size;
+	uint64_t phaddr;
+};
+
+struct mapped_soc_resource {
+	TAILQ_ENTRY(mapped_soc_resource) next;
+	struct rte_soc_addr soc_addr;
+	char path[PATH_MAX];
+	int nb_maps;
+	struct soc_map maps[SOC_MAX_RESOURCE];
+};
+
+TAILQ_HEAD(mapped_soc_res_list, mapped_soc_resource);
+
+/**
+ * Compare two SoC device address.
+ * @return
+ *	0 on addr == addr2
+ *	Positive on addr > addr2
+ *	Negative on addr < addr2
+ */
+static inline int
+rte_eal_compare_soc_addr(const struct rte_soc_addr *addr,
+			 const struct rte_soc_addr *addr2)
+{
+	if ((addr == NULL) || (addr2 == NULL))
+		return -1;
+
+	return strcmp(addr->devtree_path, addr2->devtree_path);
+}
+
+/**
+ * Scan the architecture-specific buses for the SoC devices, and the devices
+ * in the devices list.
+ *
+ * @return
+ * 	0 on success
+ */
+int rte_eal_soc_scan(void);
+
+/**
+ * Probe SoC devices for registered drivers.
+ *
+ * Call probe() function for all registered drivers that have a matching entry
+ * in its id_table for discovered devices.
+ *
+ * @return
+ *	0 on success
+ */
+int rte_eal_soc_probe(void);
+
+void *soc_map_resource(void *requested_addr, int fd, off_t offset,
+		size_t size, int additional_flags);
+void soc_unmap_resource(void *requested_addr, size_t size);
+
+/**
+ * Probe the single SoC device.
+ *
+ * Find the SoC device specified by the SoC address, then call the probe()
+ * function for the registered driver that has a matching entry in its id_table.
+ *
+ * @return
+ *	0 on success
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Find the SoC device specified by the SoC address, then call devuninit()
+ * function for the registered driver.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+void rte_eal_soc_dump(FILE *f);
+
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
2.6.3



More information about the dev mailing list