Discussion:
[dpdk-dev] [RFC 0/7] Support non-PCI devices
(too old to reply)
Jan Viktorin
2016-01-01 21:05:19 UTC
Permalink
Hello DPDK community,

I am proposing an RFC patch series that tries to add support for non-PCI
devices into DPDK. At the moment, the only way how to support such devices is
to utilize the virtual devices. As there are SoCs with integrated Ethernet MACs
(and other devices) that can be controled by DPDK, such infrastructure can be
helpful to write PMD for them. This is mostly the case of ARM SoCs. The ARMv7
SoCs have always an integrated EMAC (if any), the ARM+FPGA provides ways how
to put a custom EMACs into the SoC, and for ARM 64 there is the X-Gene board
with integrated 10G EMACs.

The patch set contains a simple self-test showing that this approach works. It
is possible to test it on any platform as it provides a fake sysfs and device
tree hierarchy.

I am introducing the pair rte_soc_device + rte_soc_driver and the probing code
for Linux. It is based on searching the /sys/bus/platform/devices and the
device-tree (for PMDs). No testing PMD is provided, just a simple test case
in app/test/test_soc.c.

I am unsure about the naming - rte_soc_*, however, it's the best one I've
devised so far.

I am aware of several code-issues and missing comments and moreover, there is
some infrastructure copied from the PCI code base. I will fix those in future
versions of the patch set if it is approved to the upstream. I'd be happy to
get some suggestions how to refactor the common code out from the PCI infra.

I am unaware of any other attempt to extend DPDK in this way so if there is
some work similar to this, I'd like to have a look at it.

Please, consider one important thing. There is no Linux Kernel driver that is
suitable for this kind of devices. Such driver must be PCI-independent, must
(should?) support no-IOMMU access to the device, must provide access to the
device memory specified in the device-tree's reg property, must give a way how
to perform DMA transfers, should be able to deliver interrupts, etc.

See the commits for more details...

Happy New Year!

Regards
Jan Viktorin

Jan Viktorin (7):
eal/common: define rte_soc_* related common interface
eal: introduce --no-soc option
eal: add common part of the SoC infra
eal/linuxapp: support SoC infra in linuxapp
eal: init SoC infra on rte_eal_init
eal/soc: make SoC infra testable on any platform
app/test: add SoC infra probe/detach test

app/test/Makefile | 3 +
app/test/soc_test_init.sh | 61 +++++
app/test/test_soc.c | 249 +++++++++++++++++
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_common_devargs.c | 6 +
lib/librte_eal/common/eal_common_options.c | 5 +
lib/librte_eal/common/eal_common_soc.c | 367 +++++++++++++++++++++++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 +
lib/librte_eal/common/eal_private.h | 12 +
lib/librte_eal/common/include/rte_devargs.h | 7 +
lib/librte_eal/common/include/rte_soc.h | 212 ++++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 3 +
lib/librte_eal/linuxapp/eal/eal.c | 4 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 409 ++++++++++++++++++++++++++++
15 files changed, 1342 insertions(+), 1 deletion(-)
create mode 100755 app/test/soc_test_init.sh
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/common/eal_common_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c
--
2.6.3
Jan Viktorin
2016-01-01 21:05:20 UTC
Permalink
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 <***@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
Stephen Hemminger
2016-01-02 18:01:44 UTC
Permalink
On Fri, 1 Jan 2016 22:05:20 +0100
Post by Jan Viktorin
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.
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??

On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.

Do you consider this will break binary compatibility since
sizeof (rte_soc_addr) is PATH_MAX (1024) and the other elements of the
union inside rte_devargs are much smaller (like 32 bytes).
Wiles, Keith
2016-01-02 18:35:08 UTC
Permalink
Post by Stephen Hemminger
On Fri, 1 Jan 2016 22:05:20 +0100
Post by Jan Viktorin
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.
I do like the idea of having a clean way to locate SoC devices and this design looks very clean to me with a brief read. Thanks Jan.
Post by Stephen Hemminger
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??
Stephen, Do you mean we have to add kernel code to support DPDK on SoC Platforms? If that is the case I would like to not require code be added to the kernel to support DPDK.
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I am not sure I agree with the optional support, as it could be stated that PCI support is optional on SoC platforms. It would be best to not treat SoC support as special compared to PCI support. Other then extra footprint it does not seem reasonable to require SoC support to be ifdef’ed in the code. Plus adding more ifdefs is not a good testing solution.

Can we detect somehow we are on a system with SoC support or even a system that supports PCI for that matter?
Post by Stephen Hemminger
Do you consider this will break binary compatibility since
sizeof (rte_soc_addr) is PATH_MAX (1024) and the other elements of the
union inside rte_devargs are much smaller (like 32 bytes).
Regards,
Keith
Jan Viktorin
2016-01-02 18:52:16 UTC
Permalink
On Sat, 2 Jan 2016 18:35:08 +0000
Post by Wiles, Keith
Post by Stephen Hemminger
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??
Stephen, Do you mean we have to add kernel code to support DPDK on SoC Platforms? If that is the case I would like to not require code be added to the kernel to support DPDK.
We will need a kernel module. But this is not necessarily related to the
device-tree parsing.
Post by Wiles, Keith
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I am not sure I agree with the optional support, as it could be stated that PCI support is optional on SoC platforms. It would be best to not treat SoC support as special compared to PCI support. Other then extra footprint it does not seem reasonable to require SoC support to be ifdef’ed in the code. Plus adding more ifdefs is not a good testing solution.
This is a matter of preserving ABI. Turning PCI-support to be optional
seems to be a difficult step at the moment.
Post by Wiles, Keith
Can we detect somehow we are on a system with SoC support or even a system that supports PCI for that matter?
IMO, we can detect two things: "PCI is present on the system" and
"Device tree is accessible in /proc/device-tree". Is this acceptable?
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Wiles, Keith
2016-01-02 19:13:47 UTC
Permalink
Post by Jan Viktorin
On Sat, 2 Jan 2016 18:35:08 +0000
Post by Wiles, Keith
Post by Stephen Hemminger
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??
Stephen, Do you mean we have to add kernel code to support DPDK on SoC Platforms? If that is the case I would like to not require code be added to the kernel to support DPDK.
We will need a kernel module. But this is not necessarily related to the
device-tree parsing.
Post by Wiles, Keith
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I am not sure I agree with the optional support, as it could be stated that PCI support is optional on SoC platforms. It would be best to not treat SoC support as special compared to PCI support. Other then extra footprint it does not seem reasonable to require SoC support to be ifdef’ed in the code. Plus adding more ifdefs is not a good testing solution.
This is a matter of preserving ABI. Turning PCI-support to be optional
seems to be a difficult step at the moment.
Turning off PCI support is bit hard to do as well, I was looking for a way to execute the PCI or SoC code during startup. I think having both compiled into the DPDK , but figure out how to detect if that code needs to be run is the better solution as you have pointed out later.
Post by Jan Viktorin
Post by Wiles, Keith
Can we detect somehow we are on a system with SoC support or even a system that supports PCI for that matter?
IMO, we can detect two things: "PCI is present on the system" and
"Device tree is accessible in /proc/device-tree". Is this acceptable?
I guess this would be fine with me, as I do not like us to add ifdefs.
Post by Jan Viktorin
--
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Stephen Hemminger
2016-01-02 19:14:03 UTC
Permalink
On Sat, 2 Jan 2016 19:52:16 +0100
Post by Jan Viktorin
On Sat, 2 Jan 2016 18:35:08 +0000
Post by Wiles, Keith
Post by Stephen Hemminger
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??
Stephen, Do you mean we have to add kernel code to support DPDK on SoC Platforms? If that is the case I would like to not require code be added to the kernel to support DPDK.
We will need a kernel module. But this is not necessarily related to the
device-tree parsing.
Post by Wiles, Keith
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I am not sure I agree with the optional support, as it could be stated that PCI support is optional on SoC platforms. It would be best to not treat SoC support as special compared to PCI support. Other then extra footprint it does not seem reasonable to require SoC support to be ifdef’ed in the code. Plus adding more ifdefs is not a good testing solution.
This is a matter of preserving ABI. Turning PCI-support to be optional
seems to be a difficult step at the moment.
Post by Wiles, Keith
Can we detect somehow we are on a system with SoC support or even a system that supports PCI for that matter?
IMO, we can detect two things: "PCI is present on the system" and
"Device tree is accessible in /proc/device-tree". Is this acceptable?
I am just as concerned with building and having useless code.
For now most environments can just use PCI, and having to carry around
dead code seems wasteful and potential for some security abuse as well.
Wiles, Keith
2016-01-02 19:22:23 UTC
Permalink
Post by Stephen Hemminger
On Sat, 2 Jan 2016 19:52:16 +0100
Post by Jan Viktorin
On Sat, 2 Jan 2016 18:35:08 +0000
Post by Wiles, Keith
Post by Stephen Hemminger
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
Ideally with a shared code from kernel??
Stephen, Do you mean we have to add kernel code to support DPDK on SoC Platforms? If that is the case I would like to not require code be added to the kernel to support DPDK.
We will need a kernel module. But this is not necessarily related to the
device-tree parsing.
Post by Wiles, Keith
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I am not sure I agree with the optional support, as it could be stated that PCI support is optional on SoC platforms. It would be best to not treat SoC support as special compared to PCI support. Other then extra footprint it does not seem reasonable to require SoC support to be ifdef’ed in the code. Plus adding more ifdefs is not a good testing solution.
This is a matter of preserving ABI. Turning PCI-support to be optional
seems to be a difficult step at the moment.
Post by Wiles, Keith
Can we detect somehow we are on a system with SoC support or even a system that supports PCI for that matter?
IMO, we can detect two things: "PCI is present on the system" and
"Device tree is accessible in /proc/device-tree". Is this acceptable?
I am just as concerned with building and having useless code.
For now most environments can just use PCI, and having to carry around
dead code seems wasteful and potential for some security abuse as well.
Hi Stephen,

With including every archive with the include whole archive option means we already have a huge amount of dead code in a DPDK image :-( Adding a bit more is not going to make a difference IMO. Also a system without PCI could be a security abuse too.

I think we just figure out how not to call the PCI or SoC code at runtime if not supported and compile it in always.
Jan Viktorin
2016-01-02 18:45:40 UTC
Permalink
On Sat, 2 Jan 2016 10:01:44 -0800
Post by Stephen Hemminger
On Fri, 1 Jan 2016 22:05:20 +0100
Post by Jan Viktorin
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.
Yes, DPDK needs to work in embedded environments with device tree.
Would it be possible reimplement device tree parsing in user space?
This is possible, I've already done a simple library for this few years
ago [1]. However, I don't think it is suitable for DPDK.
Post by Stephen Hemminger
Ideally with a shared code from kernel??
I have no idea what kernel code do you mean to share with... the
drivers/of/*? In userspace, the device-tree is accessible via the
filesystem (/proc/device-tree). So, I cannot see any overlap with
the kernel code.
Post by Stephen Hemminger
On a pratical level, the new SoC support must be optional
(via DPDK config infrastructure), since most architectures won't be using it.
In most cases, it is better from usability if everything is runtime based,
but with SoC this is a platform/architecture configuration.
I agree. In this RFC, it is not optional yet. On the EAL level, it's a
matter of the right ifdefs and Makefile conditionals (I think) - it does
not look to be an issue from my point of view.

The problem will arise with the lib/* stuff as eg. librte_ether depends
on pci-specific data structures very deeply. I've just finished a quick
raw librte_ether extension of the SoC devices support trying to preserve
API/ABI. Although, it is hopefully possible to preserve ABI (with SoC
disabled), the code becomes a little bit spagetti-like...
Post by Stephen Hemminger
Do you consider this will break binary compatibility since
sizeof (rte_soc_addr) is PATH_MAX (1024) and the other elements of the
union inside rte_devargs are much smaller (like 32 bytes).
I had a bad feeling about this... Originally, I started with a pointer
'const char *' so it can be done that way... However, this brings
compilator mad as it does not allow to cast char * -> const char *
because of the strict DPDK compilation settings. I didn't find any
workaround yet. I think I can make it just 'char *' for the next version
of the patch set.


[1] https://github.com/jviki/dtree
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Jan Viktorin
2016-01-03 17:12:43 UTC
Permalink
On Sat, 2 Jan 2016 19:45:40 +0100
Post by Jan Viktorin
Post by Stephen Hemminger
Do you consider this will break binary compatibility since
sizeof (rte_soc_addr) is PATH_MAX (1024) and the other elements of the
union inside rte_devargs are much smaller (like 32 bytes).
I had a bad feeling about this... Originally, I started with a pointer
'const char *' so it can be done that way... However, this brings
compilator mad as it does not allow to cast char * -> const char *
because of the strict DPDK compilation settings. I didn't find any
workaround yet. I think I can make it just 'char *' for the next version
of the patch set.
Having rte_devargs to contain only char * instead of char[PATH_MAX]
brings an issue. There is no common devargs_free function. Inside the
function rte_eal_devargs_add, I must malloc memory here to fill the
devtree_path. But there is no general way to free it. At least, I
didn't find such code... I need to do this:

108 case RTE_DEVTYPE_WHITELISTED_SOC:
109 case RTE_DEVTYPE_BLACKLISTED_SOC:
110 devargs->soc.addr.devtree_path = strdup(buf);

because the buf variable is deallocated at the end of the function.

In fact, I do not clearly understand the rte_eal_devargs_add function.
What is the expected input? The call to rte_eal_parse_devargs_str
separates the string into drvname and drvargs. What are the drvargs
supposted to be? I'd expect the user types -w <deviceid> or -b <deviceid>
(for PCI <deviceid> is the quaternion, for SoC it's the device-tree
path).

Regards
Jan
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Wiles, Keith
2016-01-04 15:21:36 UTC
Permalink
Post by Jan Viktorin
On Sat, 2 Jan 2016 19:45:40 +0100
Post by Jan Viktorin
Post by Stephen Hemminger
Do you consider this will break binary compatibility since
sizeof (rte_soc_addr) is PATH_MAX (1024) and the other elements of the
union inside rte_devargs are much smaller (like 32 bytes).
I had a bad feeling about this... Originally, I started with a pointer
'const char *' so it can be done that way... However, this brings
compilator mad as it does not allow to cast char * -> const char *
because of the strict DPDK compilation settings. I didn't find any
workaround yet. I think I can make it just 'char *' for the next version
of the patch set.
Having rte_devargs to contain only char * instead of char[PATH_MAX]
brings an issue. There is no common devargs_free function. Inside the
function rte_eal_devargs_add, I must malloc memory here to fill the
devtree_path. But there is no general way to free it. At least, I
110 devargs->soc.addr.devtree_path = strdup(buf);
because the buf variable is deallocated at the end of the function.
In fact, I do not clearly understand the rte_eal_devargs_add function.
What is the expected input? The call to rte_eal_parse_devargs_str
separates the string into drvname and drvargs. What are the drvargs
supposted to be? I'd expect the user types -w <deviceid> or -b <deviceid>
(for PCI <deviceid> is the quaternion, for SoC it's the device-tree
path).
Regards
Jan
--
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, C
Jan Viktorin
2016-01-01 21:05:21 UTC
Permalink
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 29942ea..c9e294c 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -838,6 +839,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;

+ case OPT_NO_SOC_NUM:
+ conf->no_soc = 1;
+ break;
+
case OPT_NO_HPET_NUM:
conf->no_hpet = 1;
break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 5f1367e..3a98e94 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -67,6 +67,7 @@ struct internal_config {
unsigned hugepage_unlink; /**< true to unlink backing files */
volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
volatile unsigned no_pci; /**< true to disable PCI */
+ volatile unsigned no_soc; /**< true to disable SoC */
volatile unsigned no_hpet; /**< true to disable HPET */
volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index a881c62..ba1e704 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -69,6 +69,8 @@ enum {
OPT_NO_HUGE_NUM,
#define OPT_NO_PCI "no-pci"
OPT_NO_PCI_NUM,
+#define OPT_NO_SOC "no-soc"
+ OPT_NO_SOC_NUM,
#define OPT_NO_SHCONF "no-shconf"
OPT_NO_SHCONF_NUM,
#define OPT_SOCKET_MEM "socket-mem"
--
2.6.3
Jan Viktorin
2016-01-01 21:05:22 UTC
Permalink
Probing and detaching of devices. The code is heavily based on the PCI infra.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_soc.c | 367 +++++++++++++++++++++++++++++++++
lib/librte_eal/common/eal_private.h | 12 ++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
3 files changed, 380 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..8a0edf3
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,367 @@
+/*-
+ * 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.
+ */
+
+#include <string.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/queue.h>
+#include <sys/mman.h>
+
+#include <rte_interrupts.h>
+#include <rte_log.h>
+#include <rte_soc.h>
+#include <rte_per_lcore.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_devargs.h>
+
+#include "eal_private.h"
+
+struct soc_driver_list soc_driver_list;
+struct soc_device_list soc_device_list;
+
+static struct rte_devargs *soc_devargs_lookup(struct rte_soc_device *dev)
+{
+ struct rte_devargs *devargs;
+
+ TAILQ_FOREACH(devargs, &devargs_list, next) {
+ if (devargs->type != RTE_DEVTYPE_BLACKLISTED_SOC
+ && devargs->type != RTE_DEVTYPE_WHITELISTED_SOC)
+ continue;
+
+ if (!rte_eal_compare_soc_addr(&dev->addr, &devargs->soc.addr))
+ return devargs;
+ }
+
+ return NULL;
+}
+
+/* TODO: generalize and merge with PCI version */
+void *
+soc_map_resource(void *requested_addr, int fd, off_t offset, size_t size,
+ int additional_flags)
+{
+ void *mapaddr;
+
+ mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | additional_flags, fd, offset);
+ if (mapaddr == MAP_FAILED) {
+ RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n",
+ __func__, fd, requested_addr,
+ (unsigned long)size, (unsigned long)offset,
+ strerror(errno), mapaddr);
+ } else
+ RTE_LOG(DEBUG, EAL, " SoC memory mapped at %p\n", mapaddr);
+
+ return mapaddr;
+}
+
+/* TODO: generalize and merge with PCI version */
+void
+soc_unmap_resource(void *requested_addr, size_t size)
+{
+ if (requested_addr == NULL)
+ return;
+
+ if (munmap(requested_addr, size)) {
+ RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n",
+ __func__, requested_addr, (unsigned long)size,
+ strerror(errno));
+ } else
+ RTE_LOG(DEBUG, EAL, " SoC memory unmapped at %p\n",
+ requested_addr);
+}
+
+static int
+rte_eal_soc_id_match(const struct rte_soc_id *dr, const struct rte_soc_id *dev)
+{
+ int i;
+
+ if (dr == NULL || dev == NULL)
+ return 0;
+
+ if (dr->compatible == NULL || dev->compatible == NULL)
+ return 0;
+
+ for (i = 0; dr->compatible[i]; ++i) {
+ int j;
+
+ for (j = 0; dev->compatible[j]; ++j) {
+ if (!strcmp(dr->compatible[i], dev->compatible[j]))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr, struct rte_soc_device *dev)
+{
+ int ret;
+ const struct rte_soc_id *id_table;
+
+ if (dr == NULL || dev == NULL)
+ return -EINVAL;
+
+ for (id_table = dr->id_table; id_table->compatible; ++id_table) {
+ if (!rte_eal_soc_id_match(id_table, &dev->id))
+ continue;
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %i\n",
+ dev->addr.devtree_path, dev->numa_node);
+ RTE_LOG(DEBUG, EAL, " probe driver: %s\n", dr->name);
+
+ if (dev->devargs != NULL
+ && dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC) {
+ RTE_LOG(DEBUG, EAL, " Device is blacklisted, skipping\n");
+ return 1;
+ }
+
+ ret = soc_map_device(dev);
+ if (ret != 0)
+ return ret;
+
+ dev->driver = dr;
+ return dr->devinit(dr, dev);
+ }
+
+ return 1;
+}
+
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *dr, struct rte_soc_device *dev)
+{
+ const struct rte_soc_id *id_table;
+
+ if (dr == NULL || dev == NULL)
+ return -EINVAL;
+
+ for (id_table = dr->id_table; id_table->compatible; ++id_table) {
+ if (!rte_eal_soc_id_match(id_table, &dev->id))
+ continue;
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %i\n",
+ dev->addr.devtree_path, dev->numa_node);
+
+ RTE_LOG(DEBUG, EAL, " remove driver: %s %s\n",
+ dev->addr.devtree_path, dr->name);
+
+ if (dr->devuninit && (dr->devuninit(dev) < 0))
+ return -1; /* error */
+
+ dev->driver = NULL;
+ soc_unmap_device(dev);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_probe_one_driver(dr, dev);
+ if (rc < 0)
+ return -1; /* error */
+ if (rc > 0)
+ continue; /* no driver match */
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_detach_dev(dr, dev);
+ if (rc < 0)
+ return -1; /* error */
+ if (rc > 0)
+ continue; /* not driver match */
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int rc = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ rc = soc_probe_all_drivers(dev);
+ if (rc < 0)
+ goto err_return;
+
+ return 0;
+ }
+
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL, "Failed to probe device %s\n",
+ dev->addr.devtree_path);
+ return -1;
+}
+
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int rc = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ rc = soc_detach_all_drivers(dev);
+ if (rc < 0)
+ goto err_return;
+
+ TAILQ_REMOVE(&soc_device_list, dev, next);
+ return 0;
+ }
+
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL, "Failed to detach device %s\n",
+ dev->addr.devtree_path);
+ return -1;
+}
+
+int
+rte_eal_soc_probe(void)
+{
+ struct rte_soc_device *dev = NULL;
+ struct rte_devargs *devargs;
+ int probe_all = 0;
+ int rc = 0;
+
+ if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_SOC) == 0)
+ probe_all = 1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ devargs = soc_devargs_lookup(dev);
+ if (devargs != NULL)
+ dev->devargs = devargs;
+
+ /* probe _all_ or _only whitelisted_ devices */
+ if (probe_all)
+ rc = soc_probe_all_drivers(dev);
+ else if (devargs != NULL
+ && devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ rc = soc_probe_all_drivers(dev);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE,
+ "Requested device %s cannot be used",
+ dev->addr.devtree_path);
+ }
+
+ return 0;
+}
+
+#define SIZEOF_MEM_RESOURCE_ARRAY(r) (sizeof(r) / sizeof(r[0]))
+
+static int
+soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
+{
+ int i;
+
+ fprintf(f, "%s\n", dev->addr.devtree_path);
+
+ for (i = 0; dev->id.compatible && dev->id.compatible[i]; ++i)
+ fprintf(f, " %s\n", dev->id.compatible[i]);
+ for (i = 0; i != SIZEOF_MEM_RESOURCE_ARRAY(dev->mem_resource); ++i) {
+ fprintf(f, " %16.16"PRIx64" %16.16"PRIx64"\n",
+ dev->mem_resource[i].phys_addr,
+ dev->mem_resource[i].len);
+ }
+
+ return 0;
+}
+
+void
+rte_eal_soc_dump(FILE *f)
+{
+ struct rte_soc_device *dev = NULL;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next)
+ soc_dump_one_device(f, dev);
+}
+
+void
+rte_eal_soc_register(struct rte_soc_driver *dr)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, dr, next);
+}
+
+void
+rte_eal_soc_unregister(struct rte_soc_driver *dr)
+{
+ TAILQ_REMOVE(&soc_driver_list, dr, next);
+}
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 072e672..33e2029 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -36,6 +36,7 @@

#include <stdio.h>
#include <rte_pci.h>
+#include <rte_soc.h>

/**
* Initialize the memzone subsystem (private to eal).
@@ -129,6 +130,13 @@ int rte_eal_log_init(const char *id, int facility);
*/
int rte_eal_pci_init(void);

+/**
+ * This function is private to EAL.
+ * @return
+ * 0 on success
+ */
+int rte_eal_soc_init(void);
+
#ifdef RTE_LIBRTE_IVSHMEM
/**
* Init the memory from IVSHMEM devices
@@ -175,6 +183,8 @@ int pci_unbind_kernel_driver(struct rte_pci_device *dev);
*/
int pci_map_device(struct rte_pci_device *dev);

+int soc_map_device(struct rte_soc_device *dev);
+
/**
* Unmap this device
*
@@ -182,6 +192,8 @@ int pci_map_device(struct rte_pci_device *dev);
*/
void pci_unmap_device(struct rte_pci_device *dev);

+void soc_unmap_device(struct rte_soc_device *dev);
+
/**
* Map the PCI resource of a PCI device in virtual memory
*
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 26eced5..f2ed696 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -77,6 +77,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_launch.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_pci_uio.c
+SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_memory.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_tailqs.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_common_errno.c
--
2.6.3
Jan Viktorin
2016-01-01 21:05:25 UTC
Permalink
The hardcoded constant paths to sysfs and device-tree locations
makes the SoC infra difficult to test. With this code, it is
possible to override the default path by setting the appropriate
environment variables.

A test can provide a fake sysfs and device-tree hierarchy of devices.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_soc.h | 6 ++++--
lib/librte_eal/linuxapp/eal/eal_soc.c | 15 +++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 7c279b1..d7d6827 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -56,9 +56,11 @@ 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"
+#define SYSFS_SOC_DEVICES __sysfs_soc_devices
+extern const char *__sysfs_soc_devices;
/* Flat Device Tree location in the system. */
-#define FDT_ROOT "/proc/device-tree"
+#define FDT_ROOT __fdt_root
+extern const char *__fdt_root;

struct rte_soc_resource {
uint64_t phys_addr; /**< Physical address, 0 if no resource. */
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index be0e44d..aafb9c3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -46,6 +46,9 @@
#include "eal_private.h"
#include "eal_pci_init.h"

+const char *__sysfs_soc_devices = "/sys/bus/platform/devices";
+const char *__fdt_root = "/proc/device-tree";
+
int
soc_map_device(struct rte_soc_device *dev)
{
@@ -378,12 +381,24 @@ error:
int
rte_eal_soc_init(void)
{
+ char *tmp;
+
TAILQ_INIT(&soc_driver_list);
TAILQ_INIT(&soc_device_list);

if (internal_config.no_soc)
return 0;

+ if ((tmp = getenv("SYSFS_SOC_DEVICES")))
+ __sysfs_soc_devices = tmp;
+ else
+ __sysfs_soc_devices = "/sys/bus/platform/devices";
+
+ if ((tmp = getenv("FDT_ROOT")))
+ __fdt_root = tmp;
+ else
+ __fdt_root = "/proc/device-tree";
+
if (rte_eal_soc_scan() < 0) {
RTE_LOG(ERR, EAL, "%s(): Failed to scan for SoC devices\n",
__func__);
--
2.6.3
Jan Viktorin
2016-01-01 21:05:24 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/linuxapp/eal/eal.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 635ec36..8a6691d 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_devargs.h>
#include <rte_common.h>
#include <rte_version.h>
@@ -785,6 +786,9 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
#ifdef RTE_LIBRTE_IVSHMEM
if (rte_eal_ivshmem_init() < 0)
rte_panic("Cannot init IVSHMEM\n");
--
2.6.3
Jan Viktorin
2016-01-01 21:05:23 UTC
Permalink
Provide Linux-specific discovery routines. The discovery reads the
/sys/bus/platform/devices/*/uevent file for each device. If the uevent
file contains OF_FULLNAME entry (path in the Device Tree) and a list of
OF_COMPATIBLE_# entries, it is considered as a SoC device and inserted
into the soc_device_list.

We do not care about the mem_resources at the moment. We need a proper
Linux Kernel driver to support this. Gathering of the resource information
could be done by parsing reg properties in the Device Tree.

There is a possible pitfall here, if there is a device depending on another
device (eg. an EMAC with a separate DMA engine), we cannot treat it as a
single device as the relation between whose might not be described in a
standardized way. So the drivers of the particular devices must take care of
this themselfs.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 394 ++++++++++++++++++++++++++++++++++
2 files changed, 396 insertions(+)
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c

diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index f2ed696..11e2dc8 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -60,6 +60,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_uio.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_pci_vfio_mp_sync.c
+SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_lcore.c
SRCS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal_timer.c
@@ -105,6 +106,7 @@ CFLAGS_eal_hugepage_info.o := -D_GNU_SOURCE
CFLAGS_eal_pci.o := -D_GNU_SOURCE
CFLAGS_eal_pci_uio.o := -D_GNU_SOURCE
CFLAGS_eal_pci_vfio.o := -D_GNU_SOURCE
+CFLAGS_eal_soc.o := -D_GNU_SOURCE
CFLAGS_eal_common_whitelist.o := -D_GNU_SOURCE
CFLAGS_eal_common_options.o := -D_GNU_SOURCE
CFLAGS_eal_common_thread.o := -D_GNU_SOURCE
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
new file mode 100644
index 0000000..be0e44d
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -0,0 +1,394 @@
+/*-
+ * 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.
+ */
+
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <rte_log.h>
+#include <rte_pci.h>
+#include <rte_eal_memconfig.h>
+#include <rte_malloc.h>
+#include <rte_devargs.h>
+#include <rte_memcpy.h>
+
+#include "eal_filesystem.h"
+#include "eal_private.h"
+#include "eal_pci_init.h"
+
+int
+soc_map_device(struct rte_soc_device *dev)
+{
+ int rc = -1;
+
+ switch (dev->kdrv) {
+ case RTE_SOC_KDRV_NONE:
+ rc = 0;
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+void
+soc_unmap_device(struct rte_soc_device *dev)
+{
+ switch (dev->kdrv) {
+ case RTE_SOC_KDRV_NONE:
+ break;
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ break;
+ }
+}
+
+static char *
+linecpy(char *dst, const char *line, size_t max)
+{
+ size_t len = 0;
+
+ while (line[len] && line[len] != '\n')
+ len += 1;
+
+ return (char *) memcpy(dst, line, len > max? max : len);
+}
+
+static char *
+linedup(const char *line)
+{
+ size_t len = 0;
+ char *s;
+
+ while (line[len] && line[len] != '\n')
+ len += 1;
+
+ s = malloc(len + 1);
+ if (s == NULL)
+ return NULL;
+
+ memcpy(s, line, len);
+ s[len] = '\0';
+ return s;
+}
+
+static const char *
+uevent_find_entry(const char *start, const char *end,
+ const char *prefix, const char *context)
+{
+ const size_t len = strlen(prefix);
+ const char *p = start;
+
+ while (strncmp(prefix, p, len)) {
+ while (p < end && *p != '\n') {
+ p += 1;
+ }
+
+ if (p >= end) {
+ RTE_LOG(WARNING, EAL,
+ "%s(): missing uevent entry %s (%s)\n",
+ __func__, prefix, context);
+ return NULL;
+ }
+ else {
+ p += 1; /* skip end-of-line */
+ }
+ }
+
+ if (p + len < end)
+ return p + len;
+ else {
+ RTE_LOG(WARNING, EAL,
+ "%s(): missing value for uevent entry %s (%s)\n",
+ __func__, prefix, context);
+ return NULL;
+ }
+}
+
+static int
+soc_device_from_uevent(struct rte_soc_device *dev, const char *uevent)
+{
+ FILE *f;
+ struct stat st;
+ char *buf;
+ char *end;
+ char *err;
+ const char *entry;
+ unsigned long i;
+ unsigned long count;
+
+ if ((f = fopen(uevent, "r")) == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): cannot open sysfs file uevent\n",
+ __func__);
+ return -1;
+ }
+
+ if (fstat(fileno(f), &st) < 0) {
+ RTE_LOG(ERR, EAL, "%s(): cannot stat sysfs file uevent (%s)\n",
+ __func__, strerror(errno));
+ goto fail_fclose;
+ }
+
+ if (st.st_size <= 0) {
+ RTE_LOG(ERR, EAL, "%s(): sysfs file uevent seems to be empty\n",
+ __func__);
+ goto fail_fclose_skip;
+ }
+
+ buf = malloc(st.st_size + 1);
+ if (buf == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): failed to alloc memory\n", __func__);
+ goto fail_fclose;
+ }
+
+ if (fread(buf, 1, st.st_size, f) == 0) {
+ RTE_LOG(ERR, EAL, "%s(): cannot read sysfs file uevent\n",
+ __func__);
+ goto fail_free_buf;
+ }
+ buf[st.st_size] = '\0';
+ end = buf + st.st_size;
+
+ entry = uevent_find_entry(buf, end, "OF_FULLNAME=", uevent);
+ if (entry == NULL)
+ goto fail_free_buf_skip;
+
+ linecpy((char *) dev->addr.devtree_path, entry,
+ sizeof(dev->addr.devtree_path));
+
+ RTE_LOG(DEBUG, EAL, "%s(): OF_FULLNAME=%s\n", __func__,
+ dev->addr.devtree_path);
+
+ entry = uevent_find_entry(buf, end, "OF_COMPATIBLE_N=", uevent);
+ if (entry == NULL)
+ goto fail_free_buf_skip; /* reported from uevent_find_entry */
+
+ count = strtoul(entry, &err, 0);
+ if (err == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): failed to parse OF_COMPATIBLE_N\n",
+ __func__);
+ goto fail_free_buf;
+ }
+
+ RTE_LOG(DEBUG, EAL, "%s(): OF_COMPATIBLE_N=%lu\n", __func__, count);
+
+ dev->id.compatible = calloc(count + 1, sizeof(*dev->id.compatible));
+ if (dev->id.compatible == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): failed to alloc memory\n",
+ __func__);
+ goto fail_free_buf;
+ }
+
+ if (count > 9999) /* FIXME: better way? */
+ rte_exit(EXIT_FAILURE, "Strange count of OF_COMPATIBLE entries"
+ "in sysfs uevent\n");
+
+ for (i = 0; i < count; ++i) {
+ char prefix[strlen("OF_COMPATIBLE_NNNN=")];
+ snprintf(prefix, sizeof(prefix), "OF_COMPATIBLE_%lu=", i);
+
+ entry = uevent_find_entry(buf, end, prefix, uevent);
+ if (entry == NULL) {
+ while (i-- > 0)
+ free(dev->id.compatible[i]);
+ goto fail_id_compatible;
+ }
+
+ dev->id.compatible[i] = linedup(entry);
+ RTE_LOG(DEBUG, EAL, "%s(): %s%s\n", __func__, prefix,
+ dev->id.compatible[i]);
+ if (dev->id.compatible[i] == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): failed to alloc memory\n",
+ __func__);
+
+ while (i-- > 0)
+ free(dev->id.compatible[i]);
+ goto fail_id_compatible;
+ }
+ }
+
+ dev->id.compatible[count] = NULL;
+ return 0;
+
+fail_id_compatible:
+ free(dev->id.compatible);
+fail_free_buf:
+ free(buf);
+fail_fclose:
+ fclose(f);
+ return -1;
+fail_free_buf_skip:
+ free(buf);
+fail_fclose_skip:
+ fclose(f);
+ return 1;
+}
+
+static void
+soc_device_uevent_free(struct rte_soc_device *dev)
+{
+ if (!dev)
+ return;
+
+ if (dev->id.compatible) {
+ int i;
+
+ for (i = 0; dev->id.compatible[i]; ++i)
+ free(dev->id.compatible[i]);
+
+ free(dev->id.compatible);
+ }
+}
+
+static void
+soc_device_free(struct rte_soc_device *dev)
+{
+ soc_device_uevent_free(dev);
+ free(dev);
+}
+
+static int
+soc_scan_one(const char *dirname)
+{
+ char filename[PATH_MAX];
+ struct rte_soc_device *dev;
+ unsigned long tmp;
+ int rc;
+
+ dev = calloc(1, sizeof(*dev));
+ if (dev == NULL)
+ return -1;
+
+ snprintf(filename, sizeof(filename), "%s/numa_node", dirname);
+ if (access(filename, R_OK) != 0) {
+ /* no NUMA support */
+ dev->numa_node = 0;
+ } else {
+ if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ free(dev);
+ return -1;
+ }
+ dev->numa_node = tmp;
+ }
+
+ snprintf(filename, sizeof(filename), "%s/uevent", dirname);
+ rc = soc_device_from_uevent(dev, filename);
+ if (rc) {
+ free(dev);
+ return rc;
+ }
+
+ dev->driver = NULL;
+ dev->kdrv = RTE_SOC_KDRV_NONE;
+
+ if (TAILQ_EMPTY(&soc_device_list)) {
+ TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+ } else {
+ struct rte_soc_device *dev2;
+ int rc;
+
+ TAILQ_FOREACH(dev2, &soc_device_list, next) {
+ rc = rte_eal_compare_soc_addr(&dev->addr, &dev2->addr);
+ if (rc > 0)
+ continue;
+
+ if (rc < 0) {
+ TAILQ_INSERT_BEFORE(dev2, dev, next);
+ } else { /* already exists */
+ dev2->kdrv = dev->kdrv;
+ memmove(dev2->mem_resource, dev->mem_resource,
+ sizeof(dev->mem_resource));
+ soc_device_free(dev);
+ }
+ return 0;
+ }
+ TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+ }
+
+ return 0;
+}
+
+int
+rte_eal_soc_scan(void)
+{
+ struct dirent *e;
+ DIR *dir;
+ char dirname[PATH_MAX];
+
+ dir = opendir(SYSFS_SOC_DEVICES);
+ if (dir == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
+ __func__, strerror(errno));
+ return -1;
+ }
+
+ while ((e = readdir(dir)) != NULL) {
+ if (e->d_name[0] == '.')
+ continue;
+
+ snprintf(dirname, sizeof(dirname), "%s/%s", SYSFS_SOC_DEVICES,
+ e->d_name);
+ if (soc_scan_one(dirname) < 0)
+ goto error;
+ }
+
+ closedir(dir);
+ return 0;
+
+error:
+ closedir(dir);
+ return -1;
+}
+
+int
+rte_eal_soc_init(void)
+{
+ TAILQ_INIT(&soc_driver_list);
+ TAILQ_INIT(&soc_device_list);
+
+ if (internal_config.no_soc)
+ return 0;
+
+ if (rte_eal_soc_scan() < 0) {
+ RTE_LOG(ERR, EAL, "%s(): Failed to scan for SoC devices\n",
+ __func__);
+ return -1;
+ }
+
+ return 0;
+}
--
2.6.3
Jan Viktorin
2016-01-01 21:05:26 UTC
Permalink
The test probes for devices and tries to match with the test_driver0. The
test_driver0 assumes a fake device. The fake device is created by the provided
script soc_test_init.sh which creates a fake sysfs and fdt in the current
directory. Execute the test by:

$ ./soc_test_init.sh setup
$ export SYSFS_SOC_DEVICES=`pwd`/sys/bus/platform/devices
$ expott FDT_ROOT=`pwd`/device-tree
$ build/app/test --no-pci --no-huge --no-hpet -c 0x1 -n 1
$ ./soc_test_init.sh clean

I did not find a proper way how to set the compatible property (a const char *)
list for the driver as DPDK has very strict compilation settings. I have no
idea how to setup the compatible with the const string unless the following
option is set:

-Wno-error=incompatible-pointer-types

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
app/test/Makefile | 3 +
app/test/soc_test_init.sh | 61 ++++++++++++
app/test/test_soc.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 313 insertions(+)
create mode 100755 app/test/soc_test_init.sh
create mode 100644 app/test/test_soc.c

diff --git a/app/test/Makefile b/app/test/Makefile
index ec33e1a..5bd2f16 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -44,6 +44,7 @@ APP = test
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
SRCS-y += test.c
SRCS-y += test_pci.c
+SRCS-y += test_soc.c
SRCS-y += test_prefetch.c
SRCS-y += test_byteorder.c
SRCS-y += test_per_lcore.c
@@ -160,6 +161,8 @@ CFLAGS += $(WERROR_FLAGS)

CFLAGS += -D_GNU_SOURCE

+CFLAGS_test_soc.o += -Wno-error=incompatible-pointer-types
+
# Disable VTA for memcpy test
ifeq ($(CC), gcc)
ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
diff --git a/app/test/soc_test_init.sh b/app/test/soc_test_init.sh
new file mode 100755
index 0000000..1d808ee
--- /dev/null
+++ b/app/test/soc_test_init.sh
@@ -0,0 +1,61 @@
+#! /bin/sh
+
+uevent_create()
+{
+ echo "OF_FULLNAME=/rootbus/testdevice"
+ echo "OF_COMPATIBLE_N=1"
+ echo "OF_COMPATIBLE_0=dpdk,test-device"
+}
+
+setup_sys()
+{
+ cd ${1}
+
+ mkdir -p bus/platform/devices
+ cd bus/platform/devices
+
+ mkdir ***@testdevice
+ uevent_create > ***@testdevice/uevent
+
+ cd ${2}
+}
+
+setup_fdt()
+{
+ cd ${1}
+
+ mkdir rootbus
+ mkdir rootbus/testdevice
+ echo -e 'dpdk,test-device\0' > rootbus/testdevice/compatible
+ echo -e 'test-device\0' > rootbus/testdevice/name
+
+ cd ${2}
+}
+
+setup()
+{
+ mkdir sys
+ mkdir device-tree
+
+ cur=`pwd`
+ sys=$cur/sys
+ fdt=$cur/device-tree
+
+ setup_sys "$sys" "$cur"
+ setup_fdt "$fdt" "$cur"
+}
+
+clean()
+{
+ rm -rf device-tree
+ rm -rf sys
+}
+
+if [ "${1}" = "setup" ]; then
+ setup
+elif [ "${1}" = "clean" ]; then
+ clean
+else
+ echo "Specify either 'setup' or 'clean' command" >&2
+ exit -1
+fi
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
new file mode 100644
index 0000000..6042626
--- /dev/null
+++ b/app/test/test_soc.c
@@ -0,0 +1,249 @@
+/*-
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_interrupts.h>
+#include <rte_soc.h>
+#include <rte_ethdev.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+
+#define NUM_MAX_DRIVERS 256
+
+static unsigned int soc_dev_init_count;
+static unsigned int soc_dev_uninit_count;
+
+static int test_driver0_init(struct rte_soc_driver *dr,
+ struct rte_soc_device *dev)
+{
+ printf("Initialize %s\n", dr->name);
+ printf("Device: %s\n", dev->addr.devtree_path);
+
+ soc_dev_init_count += 1;
+ return 0;
+}
+
+static int test_driver0_uninit(struct rte_soc_device *dev)
+{
+ if (dev->driver == NULL) {
+ printf("Uninitialize device %s without any driver\n",
+ dev->addr.devtree_path);
+ } else {
+ printf("Uninitialize device %s bound to %s\n",
+ dev->addr.devtree_path, dev->driver->name);
+ }
+
+ soc_dev_uninit_count += 1;
+ return 0;
+}
+
+static const char *test_driver0_compatible[] = {
+ "dpdk,test-device",
+ NULL
+};
+
+static const struct rte_soc_id test_driver0_id_table[] = {
+ {
+ .compatible = test_driver0_compatible
+ },
+ {
+ .compatible = NULL
+ }
+};
+
+static struct rte_soc_driver test_driver0 = {
+ .name = "test_driver0",
+ .devinit = test_driver0_init,
+ .devuninit = test_driver0_uninit,
+ .id_table = test_driver0_id_table,
+ .drv_flags = 0
+};
+
+static void
+rte_eal_soc_detach_all(void)
+{
+ struct rte_soc_device *dev = NULL;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ int rc = rte_eal_soc_detach(&dev->addr);
+ if (rc != 0) {
+ rte_exit(EXIT_FAILURE, "Failed to detach device %s\n",
+ dev->addr.devtree_path);
+ }
+ }
+}
+
+static int
+blacklist_all_devices(void)
+{
+ struct rte_soc_device *dev = NULL;
+ int i = 0;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ int rc = rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_SOC,
+ dev->addr.devtree_path);
+
+ if (rc < 0) {
+ printf("Failed to blacklist device %s\n",
+ dev->addr.devtree_path);
+ return -1;
+ }
+
+ i += 1;
+ }
+
+ printf("%u devices have been blacklisted\n", i);
+ return 0;
+}
+
+static void free_devargs_list(void)
+{
+ struct rte_devargs *devargs;
+
+ while (!TAILQ_EMPTY(&devargs_list)) {
+ devargs = TAILQ_FIRST(&devargs_list);
+ TAILQ_REMOVE(&devargs_list, devargs, next);
+ if (devargs->args)
+ free(devargs->args);
+
+ free(devargs);
+ }
+}
+
+int test_soc_run = 0; /* value checked by the multiprocess test */
+
+static int
+test_soc(void)
+{
+ struct rte_devargs_list save_devargs_list;
+ struct rte_soc_driver *dr = NULL;
+ struct rte_soc_driver *save_soc_driver_list[NUM_MAX_DRIVERS];
+ int num_drivers = 0;
+ int i;
+ int rc = 0;
+
+ if (TAILQ_EMPTY(&soc_device_list)) {
+ printf("There are no SoC devices detected\n");
+ return -1;
+ }
+
+ printf("Dump all devices\n");
+ rte_eal_soc_dump(stdout);
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rte_eal_soc_unregister(dr);
+ save_soc_driver_list[num_drivers++] = dr;
+ }
+
+ rte_eal_soc_register(&test_driver0);
+
+ soc_dev_init_count = 0;
+ soc_dev_uninit_count = 0;
+
+ printf("Probe SoC devices\n");
+ rte_eal_soc_probe();
+
+ if (soc_dev_init_count == 0) {
+ printf("No SoC device detected\n");
+ rc = -1;
+ goto failed;
+ }
+
+ rte_eal_soc_detach_all();
+
+ if (soc_dev_init_count != soc_dev_uninit_count) {
+ printf("Detached %u out of %u devices\n",
+ soc_dev_uninit_count, soc_dev_init_count);
+ rc = -1;
+ goto failed;
+ }
+
+ if (rte_eal_soc_scan()) {
+ printf("Failed to scan for SoC devices\n");
+ rc = -1;
+ goto failed;
+ }
+
+ if (TAILQ_EMPTY(&soc_device_list)) {
+ printf("There are no SoC devices detected\n");
+ rc = -1;
+ goto failed;
+ }
+
+ save_devargs_list = devargs_list;
+ TAILQ_INIT(&devargs_list);
+
+ if (blacklist_all_devices()) {
+ free_devargs_list();
+ devargs_list = save_devargs_list;
+ rc = -1;
+ goto failed_devargs_restore;
+ }
+
+ soc_dev_init_count = 0;
+ soc_dev_uninit_count = 0;
+
+ printf("Probe SoC devices while all are blacklisted\n");
+ rte_eal_soc_probe();
+
+ if (soc_dev_init_count != 0) {
+ printf("%u devices where probed while blacklisted\n",
+ soc_dev_init_count);
+ rc = -1;
+ }
+
+failed_devargs_restore:
+ free_devargs_list();
+ devargs_list = save_devargs_list;
+
+failed:
+ rte_eal_soc_unregister(&test_driver0);
+
+ test_soc_run = 1;
+
+ for (i = 0; i < num_drivers; ++i)
+ rte_eal_soc_register(save_soc_driver_list[i]);
+
+ return rc;
+}
+
+static struct test_command soc_cmd = {
+ .command = "soc_autotest",
+ .callback = test_soc,
+};
+REGISTER_TEST_COMMAND(soc_cmd);
--
2.6.3
Jan Viktorin
2016-05-06 13:47:42 UTC
Permalink
Hello,

as a part of reworking the rte_(pci_)device/driver core of DPDK, I am
developing support for devices connected anotherway then by the PCI bus. I call
those devices _SoC devices_ and they are similar to the kernel's
platform_device. The goal is to have access to the on-chip MACs integrated
into many SoCs.

This patch set depends on

* [PATCH v2 00/17] prepare for rte_device / rte_driver
http://thread.gmane.org/gmane.comp.networking.dpdk.devel/32387

Patches have been generated and tested on top of 84c9b5a (& 32387)

There are some BSD stubs (but I didn't test whether this is enough to not break
the BSD builds).

I've generalized certain internal (PCI-specific) functions of EAL to reuse them
by the SoC infrastructure (patches 1-5).

Then the SoC infra is introduced in quite small steps (6-22). For some of those
steps I've got an auto test (however not included to avoid introducing
dependencies on other series - (3)). Note:

* rte_soc_device/driver has a lot of common contents with rte_pci_* ones. This
is a subject of future changes - introduction of rte_driver/device. The
common members of device are:
- next,
- intr_handle,
- numa_node,
- devargs,
- kdrv.

The some for driver:
- next
- name
- drv_flags

Moreover, the addr, id and driver (from device), and devinit, devuninit
and id_tables can be generalized to some degree as well.

* Do we want a list of PCI devices/drivers, a list of SoC devices/drivers
(separated) or integrated into a single list and check for some type member?
When iterating over a generic rte_driver/device, it introduces a lot of bloat
code:

struct rte_driver *drv;
struct rte_pci_driver *pci_drv;
TAILQ_FOREACH(drv, drivers_list, next) {
if (!is_pci(drv))
continue;
pci_drv = to_pci_driver(drv);
...
}

I didn't find a way how to wrap this into something like PCI_DRV_FOREACH(...)
(sys/queue.h is not suitable for this).

* rte_soc_resource and rte_pci_resource can be generalized to rte_resource.
The similar might be possible for pci_map and mapped_pci_resource.

* RTE_*_DRV_* flags should be generalized.

* rte_soc_id has problem with the compatible property that must be const
but we need to see it as non-const (GCC doesn't like it). Thus, I've used
a workaround (union).

* rte_soc_addr contains fdt_path string - this can be connected with the FDT
API (1) if possible later.

* I parse devargs by testing presence of a prefix "soc:" (not tested).

Finally (23-28), I created the necessary glue code to connect with
librte_ether. You can see that this is not a problem anymore, however, it
duplicates code. So, at this stage, the generic rte_driver/device is not
necessary but would be helpful.

I've also investigated how the VFIO and UIO work. After refactoring of the VFIO
as done in (2), it is possible to add a SoC-VFIO layer. Similar for UIO. It is
possible to utilize uio_pdev_genirq or (patched) uio_dmem_genirq. The
uio_dmem_genirq is better (after few small changes) as it provides access to
the DMA coherent memory. The VFIO should be used on platforms with I/O MMU
and with hugepages. I think, those extensions are for 16.11 as it's another
quite long amount of code. However, it it is not necessary to break APIs.

I've already posted 3 related patch sets:

(1) [RFC 0/6] Flattened Device Tree access from DPDK
http://thread.gmane.org/gmane.comp.networking.dpdk.devel/36545

(2) [PATCH 00/15] Make VFIO support independent on PCI
http://article.gmane.org/gmane.comp.networking.dpdk.devel/38154

(3) [PATCH v1 00/10] Include resources in tests
http://thread.gmane.org/gmane.comp.networking.dpdk.devel/38459

I do my best to leave those patch sets independent on each other but they all
should finally work together.

The end :-). The patch set is designed to be merged partially, if needed
(due to its size) and at this stage it should help to solve the rte_driver /
rte_device task.

Regards
Jan

Jan Viktorin (28):
eal: make enum rte_kernel_driver non-PCI specific
eal: extract function eal_parse_sysfs_valuef
eal/linux: extract function rte_eal_unbind_kernel_driver
eal/linux: extract function rte_eal_get_kernel_driver_by_path
eal: remove pci_ prefix from pci_(un)map_resource
eal/soc: introduce very essential SoC infra definitions
eal/soc: add rte_eal_soc_register/unregister logic
eal/soc: implement SoC device discovery
eal: introduce --no-soc option
eal/soc: init SoC infra from EAL
eal/soc: implement probing of drivers
eal/soc: extend and utilize devargs
eal/soc: update device on probe when already exists
eal/soc: detect assigned kernel driver
eal/soc: map/unmap resources
eal/soc: add intr_handle
eal/soc: hack (const char *) compatible setting
eal/soc: detect numa_node of the rte_soc_device
eal/soc: add drv_flags
eal/soc: map resources conditionally
eal/soc: unbind kernel driver on probe
eal/soc: detect DMA non-coherent devices
eal: define macro container_of
ether: utilize container_of for pci_drv
ether: verify we copy info from a PCI device
ether: extract function eth_dev_get_intr_handle
ether: extract function eth_dev_get_driver_name
ether: support SoC device/driver

app/test/Makefile | 1 +
app/test/test_soc.c | 199 ++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 2 +
lib/librte_eal/bsdapp/eal/eal.c | 4 +
lib/librte_eal/bsdapp/eal/eal_pci.c | 2 +-
lib/librte_eal/bsdapp/eal/eal_soc.c | 52 +++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 11 +
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_common_dev.c | 70 +++-
lib/librte_eal/common/eal_common_devargs.c | 7 +
lib/librte_eal/common/eal_common_options.c | 5 +
lib/librte_eal/common/eal_common_pci.c | 39 --
lib/librte_eal/common/eal_common_pci_uio.c | 6 +-
lib/librte_eal/common/eal_common_soc.c | 373 ++++++++++++++++++
lib/librte_eal/common/eal_filesystem.h | 5 +
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 +
lib/librte_eal/common/eal_private.h | 96 +++++
lib/librte_eal/common/include/rte_common.h | 16 +
lib/librte_eal/common/include/rte_dev.h | 8 +
lib/librte_eal/common/include/rte_devargs.h | 8 +
lib/librte_eal/common/include/rte_pci.h | 42 +-
lib/librte_eal/common/include/rte_soc.h | 296 ++++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/linuxapp/eal/eal.c | 98 ++++-
lib/librte_eal/linuxapp/eal/eal_pci.c | 62 +--
lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 3 +-
lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 4 +-
lib/librte_eal/linuxapp/eal/eal_soc.c | 492 ++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 13 +
lib/librte_ether/rte_ethdev.c | 163 +++++++-
lib/librte_ether/rte_ethdev.h | 33 +-
32 files changed, 1952 insertions(+), 165 deletions(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/common/eal_common_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c
--
2.8.0
Jan Viktorin
2016-05-06 13:47:43 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_dev.h | 8 ++++++++
lib/librte_eal/common/include/rte_pci.h | 10 +---------
2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index b1c0520..ad4bfeb 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -100,6 +100,14 @@ rte_pmd_debug_trace(const char *func_name, const char *fmt, ...)
} \
} while (0)

+enum rte_kernel_driver {
+ RTE_KDRV_UNKNOWN = 0,
+ RTE_KDRV_IGB_UIO,
+ RTE_KDRV_VFIO,
+ RTE_KDRV_UIO_GENERIC,
+ RTE_KDRV_NIC_UIO,
+ RTE_KDRV_NONE,
+};

/** Double linked list of device drivers. */
TAILQ_HEAD(rte_driver_list, rte_driver);
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 169b746..dab150e 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -83,6 +83,7 @@ extern "C" {
#include <inttypes.h>

#include <rte_debug.h>
+#include <rte_dev.h>
#include <rte_interrupts.h>

TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
@@ -145,15 +146,6 @@ struct rte_pci_addr {

struct rte_devargs;

-enum rte_kernel_driver {
- RTE_KDRV_UNKNOWN = 0,
- RTE_KDRV_IGB_UIO,
- RTE_KDRV_VFIO,
- RTE_KDRV_UIO_GENERIC,
- RTE_KDRV_NIC_UIO,
- RTE_KDRV_NONE,
-};
-
/**
* A structure describing a PCI device.
*/
--
2.8.0
Jan Viktorin
2016-05-06 13:47:44 UTC
Permalink
The eal_parse_sysfs_value function accepts a filename however, such interface
introduces race-conditions to the code. Introduce the variant of this function
that accepts an already opened file instead of a filename.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_filesystem.h | 5 +++++
lib/librte_eal/linuxapp/eal/eal.c | 36 +++++++++++++++++++++++-----------
2 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/lib/librte_eal/common/eal_filesystem.h b/lib/librte_eal/common/eal_filesystem.h
index fdb4a70..7875454 100644
--- a/lib/librte_eal/common/eal_filesystem.h
+++ b/lib/librte_eal/common/eal_filesystem.h
@@ -43,6 +43,7 @@
/** Path of rte config file. */
#define RUNTIME_CONFIG_FMT "%s/.%s_config"

+#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <unistd.h>
@@ -115,4 +116,8 @@ eal_get_hugefile_temp_path(char *buffer, size_t buflen, const char *hugedir, int
* Used to read information from files on /sys */
int eal_parse_sysfs_value(const char *filename, unsigned long *val);

+/** Function to read a single numeric value from a file on the filesystem.
+ * Used to read information from files on /sys */
+int eal_parse_sysfs_valuef(FILE *f, unsigned long *val);
+
#endif /* EAL_FILESYSTEM_H */
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 4b28197..e8fce6b 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -126,13 +126,30 @@ rte_eal_get_configuration(void)
return &rte_config;
}

+int
+eal_parse_sysfs_valuef(FILE *f, unsigned long *val)
+{
+ char buf[BUFSIZ];
+ char *end = NULL;
+
+ RTE_VERIFY(f != NULL);
+
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ return -1;
+
+ *val = strtoul(buf, &end, 0);
+ if ((buf[0] == '\0') || (end == NULL) || (*end != '\n'))
+ return -2;
+
+ return 0;
+}
+
/* parse a sysfs (or other) file containing one integer value */
int
eal_parse_sysfs_value(const char *filename, unsigned long *val)
{
+ int ret;
FILE *f;
- char buf[BUFSIZ];
- char *end = NULL;

if ((f = fopen(filename, "r")) == NULL) {
RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
@@ -140,21 +157,18 @@ eal_parse_sysfs_value(const char *filename, unsigned long *val)
return -1;
}

- if (fgets(buf, sizeof(buf), f) == NULL) {
+ ret = eal_parse_sysfs_valuef(f, val);
+ if (ret == -1) {
RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
- __func__, filename);
- fclose(f);
- return -1;
+ __func__, filename);
}
- *val = strtoul(buf, &end, 0);
- if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
+ else if (ret < 0) {
RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
__func__, filename);
- fclose(f);
- return -1;
}
+
fclose(f);
- return 0;
+ return ret;
}
--
2.8.0
Jan Viktorin
2016-05-06 13:47:45 UTC
Permalink
Generalize the PCI-specific pci_unbind_kernel_driver. It is now divided into
two parts. First, determination of the path and string identification of the
device to be unbound. Second, the actual unbind operation which is generic.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_private.h | 13 +++++++++++++
lib/librte_eal/linuxapp/eal/eal.c | 26 ++++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_pci.c | 33 +++++++++------------------------
3 files changed, 48 insertions(+), 24 deletions(-)

diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 81816a6..3fb8353 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -289,6 +289,19 @@ int rte_eal_alarm_init(void);
int rte_eal_check_module(const char *module_name);

/**
+ * Unbind kernel driver bound to the device specified by the given devpath,
+ * and its string identification.
+ *
+ * @param devpath path to the device directory ("/sys/.../devices/<name>")
+ * @param devid identification of the device (<name>)
+ *
+ * @return
+ * -1 unbind has failed
+ * 0 module has been unbound
+ */
+int rte_eal_unbind_kernel_driver(const char *devpath, const char *devid);
+
+/**
* Get cpu core_id.
*
* This function is private to the EAL.
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index e8fce6b..844f958 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -949,3 +949,29 @@ rte_eal_check_module(const char *module_name)
/* Module has been found */
return 1;
}
+
+int
+rte_eal_unbind_kernel_driver(const char *devpath, const char *devid)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+
+ snprintf(filename, sizeof(filename),
+ "%s/driver/unbind", devpath);
+
+ f = fopen(filename, "w");
+ if (f == NULL) /* device was not bound */
+ return 0;
+
+ if (fwrite(devid, strlen(devid), 1, f) == 0) {
+ RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
+ filename);
+ goto error;
+ }
+
+ fclose(f);
+ return 0;
+error:
+ fclose(f);
+ return -1;
+}
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index fd7e34f..312cb14 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -59,38 +59,23 @@ int
pci_unbind_kernel_driver(struct rte_pci_device *dev)
{
int n;
- FILE *f;
- char filename[PATH_MAX];
- char buf[BUFSIZ];
+ char devpath[PATH_MAX];
+ char devid[BUFSIZ];
struct rte_pci_addr *loc = &dev->addr;

- /* open /sys/bus/pci/devices/AAAA:BB:CC.D/driver */
- snprintf(filename, sizeof(filename),
- SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/driver/unbind",
+ /* devpath /sys/bus/pci/devices/AAAA:BB:CC.D */
+ snprintf(devpath, sizeof(devpath),
+ SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
loc->domain, loc->bus, loc->devid, loc->function);

- f = fopen(filename, "w");
- if (f == NULL) /* device was not bound */
- return 0;
-
- n = snprintf(buf, sizeof(buf), PCI_PRI_FMT "\n",
+ n = snprintf(devid, sizeof(devid), PCI_PRI_FMT "\n",
loc->domain, loc->bus, loc->devid, loc->function);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
+ if ((n < 0) || (n >= (int)sizeof(devid))) {
RTE_LOG(ERR, EAL, "%s(): snprintf failed\n", __func__);
- goto error;
- }
- if (fwrite(buf, n, 1, f) == 0) {
- RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
- filename);
- goto error;
+ return -1;
}

- fclose(f);
- return 0;
-
-error:
- fclose(f);
- return -1;
+ return rte_eal_unbind_kernel_driver(devpath, devid);
}

static int
--
2.8.0
Jianbo Liu
2016-05-13 01:22:23 UTC
Permalink
Post by Jan Viktorin
Generalize the PCI-specific pci_unbind_kernel_driver. It is now divided into
two parts. First, determination of the path and string identification of the
device to be unbound. Second, the actual unbind operation which is generic.
---
lib/librte_eal/common/eal_private.h | 13 +++++++++++++
lib/librte_eal/linuxapp/eal/eal.c | 26 ++++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_pci.c | 33 +++++++++------------------------
3 files changed, 48 insertions(+), 24 deletions(-)
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 81816a6..3fb8353 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -289,6 +289,19 @@ int rte_eal_alarm_init(void);
int rte_eal_check_module(const char *module_name);
/**
+ * Unbind kernel driver bound to the device specified by the given devpath,
+ * and its string identification.
+ *
+ *
+ * -1 unbind has failed
+ * 0 module has been unbound
+ */
+int rte_eal_unbind_kernel_driver(const char *devpath, const char *devid);
+
+/**
* Get cpu core_id.
*
* This function is private to the EAL.
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index e8fce6b..844f958 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -949,3 +949,29 @@ rte_eal_check_module(const char *module_name)
/* Module has been found */
return 1;
}
+
+int
+rte_eal_unbind_kernel_driver(const char *devpath, const char *devid)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+
+ snprintf(filename, sizeof(filename),
+ "%s/driver/unbind", devpath);
+
+ f = fopen(filename, "w");
+ if (f == NULL) /* device was not bound */
+ return 0;
+
+ if (fwrite(devid, strlen(devid), 1, f) == 0) {
+ RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
+ filename);
+ goto error;
+ }
+
+ fclose(f);
+ return 0;
+ fclose(f);
+ return -1;
+}
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index fd7e34f..312cb14 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -59,38 +59,23 @@ int
pci_unbind_kernel_driver(struct rte_pci_device *dev)
{
int n;
- FILE *f;
- char filename[PATH_MAX];
- char buf[BUFSIZ];
+ char devpath[PATH_MAX];
+ char devid[BUFSIZ];
struct rte_pci_addr *loc = &dev->addr;
- /* open /sys/bus/pci/devices/AAAA:BB:CC.D/driver */
- snprintf(filename, sizeof(filename),
- SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/driver/unbind",
+ /* devpath /sys/bus/pci/devices/AAAA:BB:CC.D */
+ snprintf(devpath, sizeof(devpath),
+ SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
loc->domain, loc->bus, loc->devid, loc->function);
- f = fopen(filename, "w");
- if (f == NULL) /* device was not bound */
- return 0;
-
- n = snprintf(buf, sizeof(buf), PCI_PRI_FMT "\n",
+ n = snprintf(devid, sizeof(devid), PCI_PRI_FMT "\n",
loc->domain, loc->bus, loc->devid, loc->function);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
+ if ((n < 0) || (n >= (int)sizeof(devid))) {
Is it better to move "(n >= (int)sizeof(devid))" before snprintf and
it has different reason from "n < 0"?
Post by Jan Viktorin
RTE_LOG(ERR, EAL, "%s(): snprintf failed\n", __func__);
- goto error;
- }
- if (fwrite(buf, n, 1, f) == 0) {
- RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
- filename);
- goto error;
+ return -1;
}
- fclose(f);
- return 0;
-
- fclose(f);
- return -1;
+ return rte_eal_unbind_kernel_driver(devpath, devid);
}
static int
--
2.8.0
Jan Viktorin
2016-05-17 18:14:24 UTC
Permalink
On Fri, 13 May 2016 09:22:23 +0800
Post by Jianbo Liu
Post by Jan Viktorin
Generalize the PCI-specific pci_unbind_kernel_driver. It is now divided into
two parts. First, determination of the path and string identification of the
device to be unbound. Second, the actual unbind operation which is generic.
---
lib/librte_eal/common/eal_private.h | 13 +++++++++++++
lib/librte_eal/linuxapp/eal/eal.c | 26 ++++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_pci.c | 33 +++++++++------------------------
3 files changed, 48 insertions(+), 24 deletions(-)
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 81816a6..3fb8353 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -289,6 +289,19 @@ int rte_eal_alarm_init(void);
int rte_eal_check_module(const char *module_name);
/**
+ * Unbind kernel driver bound to the device specified by the given devpath,
+ * and its string identification.
+ *
+ *
+ * -1 unbind has failed
+ * 0 module has been unbound
+ */
+int rte_eal_unbind_kernel_driver(const char *devpath, const char *devid);
+
+/**
* Get cpu core_id.
*
* This function is private to the EAL.
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index e8fce6b..844f958 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -949,3 +949,29 @@ rte_eal_check_module(const char *module_name)
/* Module has been found */
return 1;
}
+
+int
+rte_eal_unbind_kernel_driver(const char *devpath, const char *devid)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+
+ snprintf(filename, sizeof(filename),
+ "%s/driver/unbind", devpath);
+
+ f = fopen(filename, "w");
+ if (f == NULL) /* device was not bound */
+ return 0;
+
+ if (fwrite(devid, strlen(devid), 1, f) == 0) {
+ RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
+ filename);
+ goto error;
+ }
+
+ fclose(f);
+ return 0;
+ fclose(f);
+ return -1;
+}
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index fd7e34f..312cb14 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -59,38 +59,23 @@ int
pci_unbind_kernel_driver(struct rte_pci_device *dev)
{
int n;
- FILE *f;
- char filename[PATH_MAX];
- char buf[BUFSIZ];
+ char devpath[PATH_MAX];
+ char devid[BUFSIZ];
struct rte_pci_addr *loc = &dev->addr;
- /* open /sys/bus/pci/devices/AAAA:BB:CC.D/driver */
- snprintf(filename, sizeof(filename),
- SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/driver/unbind",
+ /* devpath /sys/bus/pci/devices/AAAA:BB:CC.D */
+ snprintf(devpath, sizeof(devpath),
+ SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
loc->domain, loc->bus, loc->devid, loc->function);
- f = fopen(filename, "w");
- if (f == NULL) /* device was not bound */
- return 0;
-
- n = snprintf(buf, sizeof(buf), PCI_PRI_FMT "\n",
+ n = snprintf(devid, sizeof(devid), PCI_PRI_FMT "\n",
loc->domain, loc->bus, loc->devid, loc->function);
- if ((n < 0) || (n >= (int)sizeof(buf))) {
+ if ((n < 0) || (n >= (int)sizeof(devid))) {
Is it better to move "(n >= (int)sizeof(devid))" before snprintf and
it has different reason from "n < 0"?
I don't understant this comment. I cannot move the check for _n_ before
the snprintf as it is its return value... Can you provide an example of
your idea?

Do you mean to split the condition to if (n < 0) and else if (n >= ...)?
Post by Jianbo Liu
Post by Jan Viktorin
RTE_LOG(ERR, EAL, "%s(): snprintf failed\n", __func__);
- goto error;
- }
- if (fwrite(buf, n, 1, f) == 0) {
- RTE_LOG(ERR, EAL, "%s(): could not write to %s\n", __func__,
- filename);
- goto error;
+ return -1;
}
- fclose(f);
- return 0;
-
- fclose(f);
- return -1;
+ return rte_eal_unbind_kernel_driver(devpath, devid);
}
static int
--
2.8.0
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Jianbo Liu
2016-05-18 13:45:15 UTC
Permalink
Post by Jan Viktorin
On Fri, 13 May 2016 09:22:23 +0800
Post by Jianbo Liu
Post by Jan Viktorin
Generalize the PCI-specific pci_unbind_kernel_driver. It is now divided into
two parts. First, determination of the path and string identification of the
device to be unbound. Second, the actual unbind operation which is generic.
- if ((n < 0) || (n >= (int)sizeof(buf))) {
+ if ((n < 0) || (n >= (int)sizeof(devid))) {
Is it better to move "(n >= (int)sizeof(devid))" before snprintf and
it has different reason from "n < 0"?
I don't understant this comment. I cannot move the check for _n_ before
the snprintf as it is its return value... Can you provide an example of
your idea?
Do you mean to split the condition to if (n < 0) and else if (n >= ...)?
No, I thought the correct output of devid is a fixed-size string, and
need to check the buf length before snprintf.
but it seems unnessaray. Sorry :(
Jan Viktorin
2016-05-06 13:47:46 UTC
Permalink
Generalize the PCI-specific pci_get_kernel_driver_by_path. The function is
general enough, we have just moved it to eal.c, changed the prefix to rte_eal
and provided it privately to other parts of EAL.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_private.h | 14 ++++++++++++++
lib/librte_eal/linuxapp/eal/eal.c | 29 +++++++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_pci.c | 31 +------------------------------
3 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 3fb8353..9a81fdd 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -302,6 +302,20 @@ int rte_eal_check_module(const char *module_name);
int rte_eal_unbind_kernel_driver(const char *devpath, const char *devid);

/**
+ * Extrat the kernel driver name from the absolute path to the driver.
+ *
+ * @param filename path to the driver ("<path-to-device>/driver")
+ * @path dri_name target buffer where to place the driver name
+ * (should be at least PATH_MAX long)
+ *
+ * @return
+ * -1 on failure
+ * 0 when successful
+ * 1 when there is no such driver
+ */
+int rte_eal_get_kernel_driver_by_path(const char *filename, char *dri_name);
+
+/**
* Get cpu core_id.
*
* This function is private to the EAL.
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 844f958..a9f3ae2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -975,3 +975,32 @@ error:
fclose(f);
return -1;
}
+
+int
+rte_eal_get_kernel_driver_by_path(const char *filename, char *dri_name)
+{
+ int count;
+ char path[PATH_MAX];
+ char *name;
+
+ if (!filename || !dri_name)
+ return -1;
+
+ count = readlink(filename, path, PATH_MAX);
+ if (count >= PATH_MAX)
+ return -1;
+
+ /* For device does not have a driver */
+ if (count < 0)
+ return 1;
+
+ path[count] = '\0';
+
+ name = strrchr(path, '/');
+ if (name) {
+ strncpy(dri_name, name + 1, strlen(name + 1) + 1);
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 312cb14..162d46e 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -78,35 +78,6 @@ pci_unbind_kernel_driver(struct rte_pci_device *dev)
return rte_eal_unbind_kernel_driver(devpath, devid);
}

-static int
-pci_get_kernel_driver_by_path(const char *filename, char *dri_name)
-{
- int count;
- char path[PATH_MAX];
- char *name;
-
- if (!filename || !dri_name)
- return -1;
-
- count = readlink(filename, path, PATH_MAX);
- if (count >= PATH_MAX)
- return -1;
-
- /* For device does not have a driver */
- if (count < 0)
- return 1;
-
- path[count] = '\0';
-
- name = strrchr(path, '/');
- if (name) {
- strncpy(dri_name, name + 1, strlen(name + 1) + 1);
- return 0;
- }
-
- return -1;
-}
-
/* Map pci device */
int
rte_eal_pci_map_device(struct rte_pci_device *dev)
@@ -330,7 +301,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,

/* parse driver */
snprintf(filename, sizeof(filename), "%s/driver", dirname);
- ret = pci_get_kernel_driver_by_path(filename, driver);
+ ret = rte_eal_get_kernel_driver_by_path(filename, driver);
if (ret < 0) {
RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
free(dev);
--
2.8.0
Jan Viktorin
2016-05-06 13:47:47 UTC
Permalink
The functions pci_map_resource, pci_unmap_resource are generic so the pci_
prefix can be omitted. The functions are moved to the eal_common_dev.c so
they can be reused by other infrastructure.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/bsdapp/eal/eal_pci.c | 2 +-
lib/librte_eal/common/eal_common_dev.c | 39 ++++++++++++++++++++++++++++++
lib/librte_eal/common/eal_common_pci.c | 39 ------------------------------
lib/librte_eal/common/eal_common_pci_uio.c | 6 ++---
lib/librte_eal/common/eal_private.h | 32 ++++++++++++++++++++++++
lib/librte_eal/common/include/rte_pci.h | 32 ------------------------
lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 3 ++-
lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 4 +--
8 files changed, 79 insertions(+), 78 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 85e49f6..b5a20fa 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -228,7 +228,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,

/* if matching map is found, then use it */
offset = res_idx * pagesz;
- mapaddr = pci_map_resource(NULL, fd, (off_t)offset,
+ mapaddr = map_resource(NULL, fd, (off_t)offset,
(size_t)dev->mem_resource[res_idx].len, 0);
close(fd);
if (mapaddr == MAP_FAILED)
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 59ed3a0..d2763b0 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -36,6 +36,7 @@
#include <string.h>
#include <inttypes.h>
#include <sys/queue.h>
+#include <sys/mman.h>

#include <rte_dev.h>
#include <rte_devargs.h>
@@ -189,3 +190,41 @@ err:
RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n");
return -1;
}
+
+/* map a particular resource from a file */
+void *
+map_resource(void *requested_addr, int fd, off_t offset, size_t size,
+ int additional_flags)
+{
+ void *mapaddr;
+
+ /* Map the PCI memory resource of device */
+ mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | additional_flags, fd, offset);
+ if (mapaddr == MAP_FAILED) {
+ RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n",
+ __func__, fd, requested_addr,
+ (unsigned long)size, (unsigned long)offset,
+ strerror(errno), mapaddr);
+ } else
+ RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", mapaddr);
+
+ return mapaddr;
+}
+
+/* unmap a particular resource */
+void
+unmap_resource(void *requested_addr, size_t size)
+{
+ if (requested_addr == NULL)
+ return;
+
+ /* Unmap the PCI memory resource of device */
+ if (munmap(requested_addr, size)) {
+ RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n",
+ __func__, requested_addr, (unsigned long)size,
+ strerror(errno));
+ } else
+ RTE_LOG(DEBUG, EAL, " PCI memory unmapped at %p\n",
+ requested_addr);
+}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index f24dc4d..f85106d 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -67,7 +67,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/queue.h>
-#include <sys/mman.h>

#include <rte_interrupts.h>
#include <rte_log.h>
@@ -101,44 +100,6 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
return NULL;
}

-/* map a particular resource from a file */
-void *
-pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size,
- int additional_flags)
-{
- void *mapaddr;
-
- /* Map the PCI memory resource of device */
- mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
- MAP_SHARED | additional_flags, fd, offset);
- if (mapaddr == MAP_FAILED) {
- RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\n",
- __func__, fd, requested_addr,
- (unsigned long)size, (unsigned long)offset,
- strerror(errno), mapaddr);
- } else
- RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p\n", mapaddr);
-
- return mapaddr;
-}
-
-/* unmap a particular resource */
-void
-pci_unmap_resource(void *requested_addr, size_t size)
-{
- if (requested_addr == NULL)
- return;
-
- /* Unmap the PCI memory resource of device */
- if (munmap(requested_addr, size)) {
- RTE_LOG(ERR, EAL, "%s(): cannot munmap(%p, 0x%lx): %s\n",
- __func__, requested_addr, (unsigned long)size,
- strerror(errno));
- } else
- RTE_LOG(DEBUG, EAL, " PCI memory unmapped at %p\n",
- requested_addr);
-}
-
/*
* If vendor/device ID match, call the devinit() function of the
* driver.
diff --git a/lib/librte_eal/common/eal_common_pci_uio.c b/lib/librte_eal/common/eal_common_pci_uio.c
index f062e81..40b161d 100644
--- a/lib/librte_eal/common/eal_common_pci_uio.c
+++ b/lib/librte_eal/common/eal_common_pci_uio.c
@@ -75,7 +75,7 @@ pci_uio_map_secondary(struct rte_pci_device *dev)
return -1;
}

- void *mapaddr = pci_map_resource(uio_res->maps[i].addr,
+ void *mapaddr = map_resource(uio_res->maps[i].addr,
fd, (off_t)uio_res->maps[i].offset,
(size_t)uio_res->maps[i].size, 0);
/* fd is not needed in slave process, close it */
@@ -140,7 +140,7 @@ pci_uio_map_resource(struct rte_pci_device *dev)
return 0;
error:
for (i = 0; i < map_idx; i++) {
- pci_unmap_resource(uio_res->maps[i].addr,
+ unmap_resource(uio_res->maps[i].addr,
(size_t)uio_res->maps[i].size);
rte_free(uio_res->maps[i].path);
}
@@ -157,7 +157,7 @@ pci_uio_unmap(struct mapped_pci_resource *uio_res)
return;

for (i = 0; i != uio_res->nb_maps; i++) {
- pci_unmap_resource(uio_res->maps[i].addr,
+ unmap_resource(uio_res->maps[i].addr,
(size_t)uio_res->maps[i].size);
rte_free(uio_res->maps[i].path);
}
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9a81fdd..b8ce5b9 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -120,6 +120,38 @@ int rte_eal_log_early_init(void);
int rte_eal_log_init(const char *id, int facility);

/**
+ * @internal
+ * Map a particular resource from a file.
+ *
+ * @param requested_addr
+ * The starting address for the new mapping range.
+ * @param fd
+ * The file descriptor.
+ * @param offset
+ * The offset for the mapping range.
+ * @param size
+ * The size for the mapping range.
+ * @param additional_flags
+ * The additional flags for the mapping range.
+ * @return
+ * - On success, the function returns a pointer to the mapped area.
+ * - On error, the value MAP_FAILED is returned.
+ */
+void *map_resource(void *requested_addr, int fd, off_t offset,
+ size_t size, int additional_flags);
+
+/**
+ * @internal
+ * Unmap a particular resource.
+ *
+ * @param requested_addr
+ * The address for the unmapping range.
+ * @param size
+ * The size for the unmapping range.
+ */
+void unmap_resource(void *requested_addr, size_t size);
+
+/**
* Init the default log stream
*
* This function is private to EAL.
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index dab150e..d1d4202 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -408,38 +408,6 @@ int rte_eal_pci_map_device(struct rte_pci_device *dev);
void rte_eal_pci_unmap_device(struct rte_pci_device *dev);

/**
- * @internal
- * Map a particular resource from a file.
- *
- * @param requested_addr
- * The starting address for the new mapping range.
- * @param fd
- * The file descriptor.
- * @param offset
- * The offset for the mapping range.
- * @param size
- * The size for the mapping range.
- * @param additional_flags
- * The additional flags for the mapping range.
- * @return
- * - On success, the function returns a pointer to the mapped area.
- * - On error, the value MAP_FAILED is returned.
- */
-void *pci_map_resource(void *requested_addr, int fd, off_t offset,
- size_t size, int additional_flags);
-
-/**
- * @internal
- * Unmap a particular resource.
- *
- * @param requested_addr
- * The address for the unmapping range.
- * @param size
- * The size for the unmapping range.
- */
-void pci_unmap_resource(void *requested_addr, size_t size);
-
-/**
* Probe the single PCI device.
*
* Scan the content of the PCI bus, and find the pci device specified by pci
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
index 068694d..d543f89 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c
@@ -51,6 +51,7 @@

#include "eal_filesystem.h"
#include "eal_pci_init.h"
+#include "eal_private.h"

void *pci_map_addr = NULL;

@@ -345,7 +346,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
if (pci_map_addr == NULL)
pci_map_addr = pci_find_max_end_va();

- mapaddr = pci_map_resource(pci_map_addr, fd, 0,
+ mapaddr = map_resource(pci_map_addr, fd, 0,
(size_t)dev->mem_resource[res_idx].len, 0);
close(fd);
if (mapaddr == MAP_FAILED)
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
index 10266f8..a50639d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c
@@ -930,7 +930,7 @@ pci_vfio_map_resource(struct rte_pci_device *dev)
void *map_addr = NULL;
if (memreg[0].size) {
/* actual map of first part */
- map_addr = pci_map_resource(bar_addr, vfio_dev_fd,
+ map_addr = map_resource(bar_addr, vfio_dev_fd,
memreg[0].offset,
memreg[0].size,
MAP_FIXED);
@@ -940,7 +940,7 @@ pci_vfio_map_resource(struct rte_pci_device *dev)
if (map_addr != MAP_FAILED
&& memreg[1].offset && memreg[1].size) {
void *second_addr = RTE_PTR_ADD(bar_addr, memreg[1].offset);
- map_addr = pci_map_resource(second_addr,
+ map_addr = map_resource(second_addr,
vfio_dev_fd, memreg[1].offset,
memreg[1].size,
MAP_FIXED);
--
2.8.0
Jan Viktorin
2016-05-06 13:47:48 UTC
Permalink
Define initial structures and functions for the SoC infrastructure. We support
only a very minimal functions now. More features will be added in the following
commits. It is to be refactored when a generic rte_device/driver pair is added
to DPDK.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
app/test/Makefile | 1 +
app/test/test_soc.c | 93 ++++++++++++++++++++++
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_private.h | 4 +
lib/librte_eal/common/include/rte_soc.h | 134 ++++++++++++++++++++++++++++++++
5 files changed, 233 insertions(+), 1 deletion(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h

diff --git a/app/test/Makefile b/app/test/Makefile
index a4907d5..33c44c2 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -43,6 +43,7 @@ APP = test
#
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
SRCS-y += test.c
+SRCS-y += test_soc.c
SRCS-y += test_pci.c
SRCS-y += test_prefetch.c
SRCS-y += test_byteorder.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
new file mode 100644
index 0000000..a49fc9b
--- /dev/null
+++ b/app/test/test_soc.c
@@ -0,0 +1,93 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_soc.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+static char *safe_strdup(const char *s)
+{
+ char *c = strdup(s);
+ if (c == NULL)
+ rte_panic("failed to strdup '%s'\n", s);
+
+ return c;
+}
+
+static int test_compare_addr(void)
+{
+ struct rte_soc_addr a0;
+ struct rte_soc_addr a1;
+ struct rte_soc_addr a2;
+
+ a0.name = safe_strdup("ethernet0");
+ a0.fdt_path = NULL;
+
+ a1.name = safe_strdup("ethernet0");
+ a1.fdt_path = NULL;
+
+ a2.name = safe_strdup("ethernet1");
+ a2.fdt_path = NULL;
+
+ TEST_ASSERT(!rte_eal_compare_soc_addr(&a0, &a1),
+ "Failed to compare two soc addresses that equal");
+ TEST_ASSERT(rte_eal_compare_soc_addr(&a0, &a2),
+ "Failed to compare two soc addresses that differs");
+
+ free(a2.name);
+ free(a1.name);
+ free(a0.name);
+ return 0;
+}
+
+static int
+test_soc(void)
+{
+ if (test_compare_addr())
+ return -1;
+
+ return 0;
+}
+
+static struct test_command soc_cmd = {
+ .command = "soc_autotest",
+ .callback = test_soc,
+};
+REGISTER_TEST_COMMAND(soc_cmd);
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index f5ea0ee..a409c22 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_soc.h rte_pci.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_private.h b/lib/librte_eal/common/eal_private.h
index b8ce5b9..5145215 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -36,6 +36,7 @@

#include <stdio.h>
#include <rte_pci.h>
+#include <rte_soc.h>

/**
* Initialize the memzone subsystem (private to eal).
@@ -183,6 +184,9 @@ int rte_eal_ivshmem_init(void);
int rte_eal_ivshmem_obj_init(void);
#endif

+struct rte_soc_driver;
+struct rte_soc_device;
+
struct rte_pci_driver;
struct rte_pci_device;

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..cde588a
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -0,0 +1,134 @@
+/*-
+ * 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_
+
+/**
+ * @file
+ *
+ * RTE SoC Interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <rte_debug.h>
+
+struct rte_soc_id {
+ const char *compatible; /**< OF compatible specification */
+};
+
+struct rte_soc_addr {
+ char *name; /**< name used in sysfs */
+ char *fdt_path; /**< path to the associated node in FDT */
+};
+
+/**
+ * A structure describing a SoC device.
+ */
+struct rte_soc_device {
+ TAILQ_ENTRY(rte_soc_device) next; /**< Next probed SoC device */
+ struct rte_soc_addr addr; /**< SoC device Location */
+ struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_driver *driver; /**< Associated driver */
+};
+
+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 hotplugging.
+ */
+typedef int (soc_devuninit_t)(struct rte_soc_device *);
+
+/**
+ * A structure describing a SoC driver.
+ */
+struct rte_soc_driver {
+ TAILQ_ENTRY(rte_soc_driver) next; /**< Next in list */
+ const char *name; /**< Driver name */
+ soc_devinit_t *devinit; /**< Device initialization */
+ soc_devuninit_t *devuninit; /**< Device uninitialization */
+ const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+};
+
+/**
+ * Utility function to write a SoC device name, this device name can later be
+ * used to retrieve the corresponding rte_soc_addr using above functions.
+ *
+ * @param addr
+ * The SoC address
+ * @param output
+ * The output buffer string
+ * @param size
+ * The output buffer size
+ * @return
+ * 0 on success, negative on error.
+ */
+static inline void
+rte_eal_soc_device_name(const struct rte_soc_addr *addr,
+ char *output, size_t size)
+{
+ int ret;
+ RTE_VERIFY(addr != NULL);
+ RTE_VERIFY(size >= strlen(addr->name));
+ ret = snprintf(output, size, "%s", addr->name);
+ RTE_VERIFY(ret >= 0);
+}
+
+static inline int
+rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
+ const struct rte_soc_addr *a1)
+{
+ if (a0 == NULL || a1 == NULL)
+ return -1;
+
+ RTE_VERIFY(a0->name != NULL);
+ RTE_VERIFY(a1->name != NULL);
+
+ return strcmp(a0->name, a1->name);
+}
+
+#endif
--
2.8.0
Jan Viktorin
2016-05-06 13:47:49 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
app/test/test_soc.c | 106 ++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 23 +++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
7 files changed, 193 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index a49fc9b..f6288dc 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -74,6 +74,103 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .name = "empty_pmd0",
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .name = "empty_pmd1",
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd but '%s'", drv->name);
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}

@@ -83,6 +180,15 @@ test_soc(void)
if (test_compare_addr())
return -1;

+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 9054ad6..d956808 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -71,6 +71,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4d075df..c430b4b 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -158,4 +158,7 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;

+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..afeed2f
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,55 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index cde588a..28c1798 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -46,11 +46,17 @@ extern "C" {

#include <stdio.h>
#include <stdlib.h>
+#include <sys/queue.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>

#include <rte_debug.h>
+#include <rte_eal.h>
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+
+extern struct soc_driver_list soc_driver_list; /**< Global list of SoC drivers. */

struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -131,4 +137,21 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
return strcmp(a0->name, a1->name);
}

+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+#define RTE_EAL_SOC_REGISTER(name) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{ \
+ rte_eal_soc_register(&name.soc_drv); \
+}
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index e109361..37ab8d5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -82,6 +82,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 0404a52..6ff38b8 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -161,4 +161,8 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;

+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
--
2.8.0
Shreyansh Jain
2016-06-13 14:19:39 UTC
Permalink
-----Original Message-----
Sent: Friday, May 06, 2016 7:18 PM
Subject: [dpdk-dev] [PATCH v1 07/28] eal/soc: add
rte_eal_soc_register/unregister logic
---
app/test/test_soc.c | 106
++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 23 +++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
7 files changed, 193 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index a49fc9b..f6288dc 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -74,6 +74,103 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .name = "empty_pmd0",
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .name = "empty_pmd1",
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd but '%s'", drv->name);
Trivial: TEST_ASSERT Message should be: "... is not empty_pmd0 but..."
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}
@@ -83,6 +180,15 @@ test_soc(void)
if (test_compare_addr())
return -1;
+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}
diff --git a/lib/librte_eal/bsdapp/eal/Makefile
b/lib/librte_eal/bsdapp/eal/Makefile
index 9054ad6..d956808 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -71,6 +71,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4d075df..c430b4b 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -158,4 +158,7 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c
b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..afeed2f
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,55 @@
+/*-
+ * 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
+ *
+ * * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h
b/lib/librte_eal/common/include/rte_soc.h
index cde588a..28c1798 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -46,11 +46,17 @@ extern "C" {
#include <stdio.h>
#include <stdlib.h>
+#include <sys/queue.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <rte_debug.h>
+#include <rte_eal.h>
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+
+extern struct soc_driver_list soc_driver_list; /**< Global list of SoC drivers. */
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -131,4 +137,21 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
return strcmp(a0->name, a1->name);
}
+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+#define RTE_EAL_SOC_REGISTER(name) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{ \
+ rte_eal_soc_register(&name.soc_drv); \
+}
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile
b/lib/librte_eal/linuxapp/eal/Makefile
index e109361..37ab8d5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -82,6 +82,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 0404a52..6ff38b8 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -161,4 +161,8 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
--
2.8.0
Jan Viktorin
2016-06-13 14:25:33 UTC
Permalink
On Mon, 13 Jun 2016 14:19:39 +0000
Post by Shreyansh Jain
-----Original Message-----
Sent: Friday, May 06, 2016 7:18 PM
Subject: [dpdk-dev] [PATCH v1 07/28] eal/soc: add
rte_eal_soc_register/unregister logic
---
app/test/test_soc.c | 106
++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 23 +++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
7 files changed, 193 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index a49fc9b..f6288dc 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -74,6 +74,103 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .name = "empty_pmd0",
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .name = "empty_pmd1",
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd but '%s'", drv->name);
Trivial: TEST_ASSERT Message should be: "... is not empty_pmd0 but..."
OK, thanks.
[...]
Shreyansh Jain
2016-06-15 05:57:33 UTC
Permalink
Hi Jan,
-----Original Message-----
Sent: Monday, June 13, 2016 7:50 PM
Subject: Re: [dpdk-dev] [PATCH v1 07/28] eal/soc: add
rte_eal_soc_register/unregister logic
-----Original Message-----
Sent: Friday, May 06, 2016 7:18 PM
Stephen
Subject: [dpdk-dev] [PATCH v1 07/28] eal/soc: add
rte_eal_soc_register/unregister logic
---
app/test/test_soc.c | 106
++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 23 +++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
7 files changed, 193 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index a49fc9b..f6288dc 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -74,6 +74,103 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .name = "empty_pmd0",
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .name = "empty_pmd1",
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd but '%s'", drv->name);
Trivial: TEST_ASSERT Message should be: "... is not empty_pmd0 but..."
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}
@@ -83,6 +180,15 @@ test_soc(void)
if (test_compare_addr())
return -1;
+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}
diff --git a/lib/librte_eal/bsdapp/eal/Makefile
b/lib/librte_eal/bsdapp/eal/Makefile
index 9054ad6..d956808 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -71,6 +71,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4d075df..c430b4b 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -158,4 +158,7 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c
b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..afeed2f
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,55 @@
+/*-
+ * 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
+ *
+ * * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h
b/lib/librte_eal/common/include/rte_soc.h
index cde588a..28c1798 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -46,11 +46,17 @@ extern "C" {
#include <stdio.h>
#include <stdlib.h>
+#include <sys/queue.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <rte_debug.h>
+#include <rte_eal.h>
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked
Q.
*/
+
+extern struct soc_driver_list soc_driver_list; /**< Global list of SoC drivers. */
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -131,4 +137,21 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr
*a0,
return strcmp(a0->name, a1->name);
}
+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+#define RTE_EAL_SOC_REGISTER(name) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{ \
+ rte_eal_soc_register(&name.soc_drv); \
It should be 'rte_eal_soc_register(&name)'.
As a user of 'RTE_EAL_SOC_REGISTER', I would pass reference to 'rte_soc_driver' object. It doesn't have any 'soc_drv' member.

I am guessing that because you have created a wrapper structure 'test_wrapper' in test_soc.c which contains a 'soc_drv', the macro reflects that usage.
+}
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile
b/lib/librte_eal/linuxapp/eal/Makefile
index e109361..37ab8d5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -82,6 +82,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) +=
eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 0404a52..6ff38b8 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -161,4 +161,8 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.04;
--
2.8.0
-
Shreyansh
Jan Viktorin
2016-06-15 09:50:03 UTC
Permalink
On Wed, 15 Jun 2016 05:57:33 +0000
Post by Shreyansh Jain
Hi Jan,
-----Original Message-----
Sent: Monday, June 13, 2016 7:50 PM
Subject: Re: [dpdk-dev] [PATCH v1 07/28] eal/soc: add
rte_eal_soc_register/unregister logic
[...]
Post by Shreyansh Jain
Post by Jan Viktorin
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .name = "empty_pmd0",
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .name = "empty_pmd1",
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
[...]
Post by Shreyansh Jain
Post by Jan Viktorin
+
+extern struct soc_driver_list soc_driver_list; /**< Global list of SoC drivers. */
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -131,4 +137,21 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr
*a0,
Post by Jan Viktorin
return strcmp(a0->name, a1->name);
}
+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+#define RTE_EAL_SOC_REGISTER(name) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{ \
+ rte_eal_soc_register(&name.soc_drv); \
It should be 'rte_eal_soc_register(&name)'.
As a user of 'RTE_EAL_SOC_REGISTER', I would pass reference to 'rte_soc_driver' object. It doesn't have any 'soc_drv' member.
But eth_driver would have it. And other upper-level structs would have it as well.
Post by Shreyansh Jain
I am guessing that because you have created a wrapper structure 'test_wrapper' in test_soc.c which contains a 'soc_drv', the macro reflects that usage.
I don't assume to use rte_soc_driver directly (similarly to rte_pci_driver). However, I agree that
it is strange, we should have RTE_ETHDRV_SOC_REGISTER for such purpose (if needed).

I wanted to avoid redundant arguments to the RTE_EAL_SOC_REGISTER because the name is
used to create the constructor function. But, it seems that other parts of DPDK does not
care of this so I will probably give up and make it:

RTE_EAL_SOC_REGISTER(my_cool_drv, &my_cool_drv.soc_drv);

Thanks for your opinion. I'll fix it in v2.

Jan
[...]
Post by Shreyansh Jain
-
Shreyansh
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Jan Viktorin
2016-05-06 13:47:50 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/eal_soc.c | 40 ++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 45 ++++
lib/librte_eal/common/include/rte_soc.h | 14 ++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 282 ++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
8 files changed, 390 insertions(+)
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index d956808..7ac6c94 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -58,6 +58,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_memory.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_hugepage_info.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_thread.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_log.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_lcore.c
diff --git a/lib/librte_eal/bsdapp/eal/eal_soc.c b/lib/librte_eal/bsdapp/eal/eal_soc.c
new file mode 100644
index 0000000..f84aae9
--- /dev/null
+++ b/lib/librte_eal/bsdapp/eal/eal_soc.c
@@ -0,0 +1,40 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <rte_soc.h>
+
+int
+rte_eal_soc_scan(void)
+{
+ return 0;
+}
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index c430b4b..4a2eeaf 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -158,7 +158,10 @@ DPDK_16.07 {
rte_eal_dev_attach;
rte_eal_dev_detach;

+ soc_get_sysfs_path;
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_scan;
+ rte_eal_soc_dump;

} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index afeed2f..d8bb6d6 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -31,6 +31,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

+#include <stddef.h>
+#include <stdio.h>
#include <sys/queue.h>

#include <rte_log.h>
@@ -39,6 +41,49 @@

struct soc_driver_list soc_driver_list =
TAILQ_HEAD_INITIALIZER(soc_driver_list);
+struct soc_device_list soc_device_list =
+ TAILQ_HEAD_INITIALIZER(soc_device_list);
+
+/** Pathname of SoC devices directory. */
+#define SYSFS_SOC_DEVICES "/sys/bus/platform/devices"
+
+const char *soc_get_sysfs_path(void)
+{
+ const char *path = NULL;
+
+ path = getenv("SYSFS_SOC_DEVICES");
+ if (path == NULL)
+ return SYSFS_SOC_DEVICES;
+
+ return path;
+}
+
+/* dump one device */
+static int
+soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
+{
+ int i;
+
+ fprintf(f, "%s", dev->addr.name);
+ fprintf(f, " - fdt_path: %s\n",
+ dev->addr.fdt_path? dev->addr.fdt_path : "(none)");
+
+ for (i = 0; dev->id && dev->id[i].compatible; ++i)
+ fprintf(f, " %s\n", dev->id[i].compatible);
+
+ return 0;
+}
+
+/* dump devices on the bus */
+void
+rte_eal_soc_dump(FILE *f)
+{
+ struct rte_soc_device *dev = NULL;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ soc_dump_one_device(f, dev);
+ }
+}

/* register a driver */
void
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 28c1798..6278295 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -55,8 +55,13 @@ extern "C" {
#include <rte_eal.h>

TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */

extern struct soc_driver_list soc_driver_list; /**< Global list of SoC drivers. */
+extern struct soc_device_list soc_device_list; /**< Global list of SoC devices. */
+
+/** Return SoC scan path of the sysfs root. */
+const char *soc_get_sysfs_path(void);

struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -136,6 +141,15 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,

return strcmp(a0->name, a1->name);
}
+/**
+ * Scan for new SoC devices.
+ */
+int rte_eal_soc_scan(void);
+
+/**
+ * Dump discovered SoC devices.
+ */
+void rte_eal_soc_dump(FILE *f);

/**
* Register a SoC driver.
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 37ab8d5..85a892a 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -63,6 +63,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_xen_memory.c
endif
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_vfio.c
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
new file mode 100644
index 0000000..8dbb367
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -0,0 +1,282 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <rte_log.h>
+#include <rte_soc.h>
+
+#include "eal_private.h"
+
+static char *
+dev_read_uevent(const char *dirname)
+{
+ char filename[PATH_MAX];
+ struct stat st;
+ char *buf;
+ ssize_t total = 0;
+ int fd;
+
+ snprintf(filename, sizeof(filename), "%s/uevent", dirname);
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ RTE_LOG(WARNING, EAL, "Failed to open file %s\n", filename);
+ return strdup("");
+ }
+
+ if (fstat(fd, &st) < 0) {
+ RTE_LOG(ERR, EAL, "Failed to stat file %s\n", filename);
+ close(fd);
+ return NULL;
+ }
+
+ if (st.st_size == 0) {
+ close(fd);
+ return strdup("");
+ }
+
+ buf = malloc(st.st_size + 1);
+ if (buf == NULL) {
+ RTE_LOG(ERR, EAL, "Failed to alloc memory to read %s\n", filename);
+ close(fd);
+ return NULL;
+ }
+
+ while (total < st.st_size) {
+ ssize_t rlen = read(fd, buf + total, st.st_size - total);
+ if (rlen < 0) {
+ if (errno == EINTR)
+ continue;
+
+ RTE_LOG(ERR, EAL, "Failed to read file %s\n", filename);
+
+ free(buf);
+ close(fd);
+ return NULL;
+ }
+ if (rlen == 0) /* EOF */
+ break;
+
+ total += rlen;
+ }
+
+ buf[total] = '\0';
+ close(fd);
+
+ return buf;
+}
+
+static const char *
+dev_uevent_find(const char *uevent, const char *key)
+{
+ const size_t keylen = strlen(key);
+ const size_t total = strlen(uevent);
+ const char *p = uevent;
+
+ /* check whether it is the first key */
+ if (!strncmp(uevent, key, keylen))
+ return uevent + keylen;
+
+ /* check 2nd key or further... */
+ do {
+ p = strstr(p, key);
+ if (p == NULL)
+ break;
+
+ if (p[-1] == '\n') /* check we are at a new line */
+ return p + keylen;
+
+ p += keylen; /* skip this one */
+ } while(p - uevent < (ptrdiff_t) total);
+
+ return NULL;
+}
+
+static char *
+strdup_until_nl(const char *p)
+{
+ const char *nl = strchr(p, '\n');
+ if (nl == NULL)
+ return strdup(p); /* no newline, copy until '\0' */
+
+ return strndup(p, nl - p);
+}
+
+static int
+dev_parse_uevent(struct rte_soc_device *dev, const char *uevent)
+{
+ const char *of;
+
+ of = dev_uevent_find(uevent, "OF_FULLNAME=");
+ if (of == NULL)
+ return 1; /* don't care about this device */
+
+ dev->addr.fdt_path = strdup_until_nl(of);
+ if (dev->addr.fdt_path == NULL) {
+ RTE_LOG(ERR, PMD,
+ "Failed to alloc memory for fdt_path\n");
+ return -1;
+ }
+
+ RTE_LOG(DEBUG, EAL, "Detected device %s (%s)\n",
+ dev->addr.name, dev->addr.fdt_path);
+
+ dev->id = calloc(1, sizeof(*dev->id));
+ if (dev->id == NULL) {
+ free(dev->addr.fdt_path);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+dev_content_free(struct rte_soc_device *dev)
+{
+ if (dev->addr.fdt_path)
+ free(dev->addr.fdt_path);
+
+ free(dev->id);
+ dev->id = NULL;
+}
+
+/**
+ * Scan one SoC sysfs entry, and fill the devices list from it.
+ * We require to have the uevent file with records: OF_FULLNAME and
+ * OF_COMPATIBLE array (with at least one entry). Otherwise, such device
+ * is skipped.
+ */
+static int
+soc_scan_one(const char *dirname, const char *name)
+{
+ struct rte_soc_device *dev;
+ char *uevent;
+ int ret;
+
+ uevent = dev_read_uevent(dirname);
+ if (uevent == NULL)
+ return -1;
+
+ if (uevent[0] == '\0') {
+ /* ignore directory without uevent file */
+ free(uevent);
+ return 1;
+ }
+
+ dev = malloc(sizeof(*dev) + strlen(name) + 1);
+ if (dev == NULL) {
+ RTE_LOG(ERR, PMD, "Failed to alloc memory for %s\n", name);
+ free(uevent);
+ return -1;
+ }
+
+ memset(dev, 0, sizeof(*dev));
+ dev->addr.name = (char *) (dev + 1);
+ strcpy(dev->addr.name, name);
+
+ if ((ret = dev_parse_uevent(dev, uevent)))
+ goto fail;
+ free(uevent); /* not needed anymore */
+
+ /* device is valid, add in list (sorted) */
+ if (TAILQ_EMPTY(&soc_device_list)) {
+ TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+ } else {
+ struct rte_soc_device *dev2;
+
+ TAILQ_FOREACH(dev2, &soc_device_list, next) {
+ ret = rte_eal_compare_soc_addr(&dev->addr, &dev2->addr);
+ if (ret > 0)
+ continue;
+
+ if (ret < 0) {
+ TAILQ_INSERT_BEFORE(dev2, dev, next);
+ } else { /* already registered */
+
+ dev_content_free(dev2);
+ dev2->addr.fdt_path = dev->addr.fdt_path;
+ dev2->id = dev->id;
+ free(dev);
+ }
+ return 0;
+ }
+ TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+ }
+
+ return 0;
+
+fail:
+ free(uevent);
+ dev_content_free(dev);
+ free(dev);
+ return ret;
+}
+
+int
+rte_eal_soc_scan(void)
+{
+ struct dirent *e;
+ DIR *dir;
+ char dirname[PATH_MAX];
+
+ dir = opendir(soc_get_sysfs_path());
+ if (dir == NULL) {
+ RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
+ __func__, strerror(errno));
+ return -1;
+ }
+
+ while ((e = readdir(dir)) != NULL) {
+ if (e->d_name[0] == '.')
+ continue;
+
+ snprintf(dirname, sizeof(dirname), "%s/%s",
+ soc_get_sysfs_path(), e->d_name);
+ if (soc_scan_one(dirname, e->d_name) < 0)
+ goto error;
+ }
+ closedir(dir);
+ return 0;
+
+error:
+ closedir(dir);
+ return -1;
+}
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 6ff38b8..280622f 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -162,7 +162,11 @@ DPDK_16.07 {
rte_eal_dev_detach;

soc_driver_list;
+ soc_device_list;
+ soc_get_sysfs_path;
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_scan;
+ rte_eal_soc_dump;

} DPDK_16.04;
--
2.8.0
Jan Viktorin
2016-05-06 13:47:51 UTC
Permalink
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 3efc90f..09d64f7 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -841,6 +842,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;

+ case OPT_NO_SOC_NUM:
+ conf->no_soc = 1;
+ break;
+
case OPT_NO_HPET_NUM:
conf->no_hpet = 1;
break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 5f1367e..3a98e94 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -67,6 +67,7 @@ struct internal_config {
unsigned hugepage_unlink; /**< true to unlink backing files */
volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
volatile unsigned no_pci; /**< true to disable PCI */
+ volatile unsigned no_soc; /**< true to disable SoC */
volatile unsigned no_hpet; /**< true to disable HPET */
volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index a881c62..ba1e704 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -69,6 +69,8 @@ enum {
OPT_NO_HUGE_NUM,
#define OPT_NO_PCI "no-pci"
OPT_NO_PCI_NUM,
+#define OPT_NO_SOC "no-soc"
+ OPT_NO_SOC_NUM,
#define OPT_NO_SHCONF "no-shconf"
OPT_NO_SHCONF_NUM,
#define OPT_SOCKET_MEM "socket-mem"
--
2.8.0
Jianbo Liu
2016-05-13 03:28:18 UTC
Permalink
Post by Jan Viktorin
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 3efc90f..09d64f7 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -841,6 +842,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;
+ conf->no_soc = 1;
Could it be better to rename to enable_soc, and disable soc by default?
Post by Jan Viktorin
+ break;
+
conf->no_hpet = 1;
break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 5f1367e..3a98e94 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -67,6 +67,7 @@ struct internal_config {
unsigned hugepage_unlink; /**< true to unlink backing files */
volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
volatile unsigned no_pci; /**< true to disable PCI */
+ volatile unsigned no_soc; /**< true to disable SoC */
volatile unsigned no_hpet; /**< true to disable HPET */
volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index a881c62..ba1e704 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -69,6 +69,8 @@ enum {
OPT_NO_HUGE_NUM,
#define OPT_NO_PCI "no-pci"
OPT_NO_PCI_NUM,
+#define OPT_NO_SOC "no-soc"
+ OPT_NO_SOC_NUM,
#define OPT_NO_SHCONF "no-shconf"
OPT_NO_SHCONF_NUM,
#define OPT_SOCKET_MEM "socket-mem"
--
2.8.0
Jan Viktorin
2016-05-17 18:10:59 UTC
Permalink
On Fri, 13 May 2016 11:28:18 +0800
Post by Jianbo Liu
Post by Jan Viktorin
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 3efc90f..09d64f7 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -841,6 +842,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;
+ conf->no_soc = 1;
Could it be better to rename to enable_soc, and disable soc by default?
Sure, I tried to be consistent with PCI...

[...]
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Jan Viktorin
2016-05-06 13:47:52 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/bsdapp/eal/eal.c | 4 ++++
lib/librte_eal/common/eal_private.h | 10 ++++++++++
lib/librte_eal/linuxapp/eal/eal.c | 3 +++
lib/librte_eal/linuxapp/eal/eal_soc.c | 17 +++++++++++++++++
4 files changed, 34 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 06bfd4e..23faebd 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
#include <rte_string_fns.h>
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
+#include <rte_soc.h>
#include <rte_pci.h>
#include <rte_dev.h>
#include <rte_devargs.h>
@@ -567,6 +568,9 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
eal_check_mem_on_local_socket();

if (eal_plugins_init() < 0)
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 5145215..b27ec89 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -187,6 +187,16 @@ int rte_eal_ivshmem_obj_init(void);
struct rte_soc_driver;
struct rte_soc_device;

+/**
+ * Init the SoC infra.
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ * 0 on success, negative on error
+ */
+int rte_eal_soc_init(void);
+
struct rte_pci_driver;
struct rte_pci_device;

diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index a9f3ae2..5f190ff 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,6 +803,9 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
#ifdef RTE_LIBRTE_IVSHMEM
if (rte_eal_ivshmem_init() < 0)
rte_panic("Cannot init IVSHMEM\n");
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 8dbb367..a3b9935 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -44,6 +44,7 @@
#include <rte_log.h>
#include <rte_soc.h>

+#include "eal_internal_cfg.h"
#include "eal_private.h"

static char *
@@ -280,3 +281,19 @@ error:
closedir(dir);
return -1;
}
+
+/* Init the SoC EAL subsystem */
+int
+rte_eal_soc_init(void)
+{
+ /* for debug purposes, SoC can be disabled */
+ if (internal_config.no_soc)
+ return 0;
+
+ if (rte_eal_soc_scan() < 0) {
+ RTE_LOG(ERR, EAL, "%s(): Cannot scan SoC devices\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
--
2.8.0
Jan Viktorin
2016-05-06 13:47:53 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 200 ++++++++++++++++++++++++
lib/librte_eal/common/include/rte_soc.h | 25 +++
lib/librte_eal/linuxapp/eal/eal.c | 4 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 +
5 files changed, 235 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4a2eeaf..bd3dd11 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -163,5 +163,8 @@ DPDK_16.07 {
rte_eal_soc_unregister;
rte_eal_soc_scan;
rte_eal_soc_dump;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index d8bb6d6..d8f0c00 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -36,6 +36,8 @@
#include <sys/queue.h>

#include <rte_log.h>
+#include <rte_common.h>
+#include <rte_soc.h>

#include "eal_private.h"

@@ -58,6 +60,204 @@ const char *soc_get_sysfs_path(void)
return path;
}

+static int soc_id_match(const struct rte_soc_id *drv_id,
+ const struct rte_soc_id *dev_id)
+{
+ int i;
+ int j;
+
+ RTE_VERIFY(drv_id != NULL);
+ RTE_VERIFY(dev_id != NULL);
+
+ for (i = 0; drv_id[i].compatible; ++i) {
+ const char *drv_compat = drv_id[i].compatible;
+
+ for (j = 0; dev_id[j].compatible; ++j) {
+ const char *dev_compat = dev_id[j].compatible;
+
+ if (!strcmp(drv_compat, dev_compat))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
+ struct rte_soc_device *dev)
+{
+ int ret;
+
+ if (!soc_id_match(dr->id_table, dev->id))
+ return 1;
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+ dev->addr.name);
+ RTE_LOG(DEBUG, EAL, " probe driver %s\n", dr->name);
+
+ dev->driver = dr;
+ RTE_VERIFY(dr->devinit != NULL);
+ return dr->devinit(dr, dev);
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_probe_one_driver(dr, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/* If the IDs match, call the devuninit() function of the driver. */
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *dr,
+ struct rte_soc_device *dev)
+{
+ if ((dr == NULL) || (dev == NULL))
+ return -EINVAL;
+
+ if (!soc_id_match(dr->id_table, dev->id))
+ return 1;
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+ dev->addr.name);
+
+ RTE_LOG(DEBUG, EAL, " remove driver: %s\n", dr->name);
+
+ if (dr->devuninit && (dr->devuninit(dev) < 0))
+ return -1; /* negative value is an error */
+
+ /* clear driver structure */
+ dev->driver = NULL;
+
+ return 0;
+}
+
+/*
+ * Call the devuninit() function of all registered drivers for the given
+ * device if their IDs match.
+ *
+ * @return
+ * 0 when successful
+ * -1 if deinitialization fails
+ * 1 if no driver is found for this device.
+ */
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_detach_dev(dr, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Detach device specified by its SoC address.
+ */
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_detach_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+
+ TAILQ_REMOVE(&soc_device_list, dev, next);
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n",
+ dev->addr.name);
+ return -1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL,
+ "Requested device %s cannot be used\n", addr->name);
+ return -1;
+}
+
+/*
+ * Scan the SoC devices and call the devinit() function for all registered
+ * drivers that have a matching entry in its id_table for discovered devices.
+ */
+int
+rte_eal_soc_probe(void)
+{
+ struct rte_soc_device *dev = NULL;
+ int probe_all = 0;
+ int ret = 0;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Requested device %s"
+ " cannot be used\n", dev->addr.name);
+ }
+
+ return 0;
+}
+
/* dump one device */
static int
soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 6278295..4117ffb 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -147,6 +147,31 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
int rte_eal_soc_scan(void);

/**
+ * Probe SoC devices for registered drivers.
+ */
+int rte_eal_soc_probe(void);
+
+/**
+ * Probe the single SoC device.
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Scan the SoC devices and find the SoC device specified by the SoC
+ * address, then call the devuninit() function for registered driver
+ * that has a matching entry in its id_table for discovered device.
+ *
+ * @param addr
+ * The SoC address to close.
+ * @return
+ * - 0 on success.
+ * - Negative on error.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+/**
* Dump discovered SoC devices.
*/
void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 5f190ff..e697bb0 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -896,6 +896,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");

+ /* Probe & Initialize SoC devices */
+ if (rte_eal_soc_probe())
+ rte_panic("Cannot probe SoC\n");
+
rte_eal_mcfg_complete();

return fctret;
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 280622f..811cbf8 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -168,5 +168,8 @@ DPDK_16.07 {
rte_eal_soc_unregister;
rte_eal_soc_scan;
rte_eal_soc_dump;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.04;
--
2.8.0
Jan Viktorin
2016-05-06 13:47:54 UTC
Permalink
This code is not tested. We assume to white/blacklist SoC devices by giving
the prefix "soc:" on the command line.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_dev.c | 31 ++++++++++++++++++-----
lib/librte_eal/common/eal_common_devargs.c | 7 ++++++
lib/librte_eal/common/eal_common_soc.c | 39 ++++++++++++++++++++++++++++-
lib/librte_eal/common/include/rte_devargs.h | 8 ++++++
lib/librte_eal/common/include/rte_soc.h | 28 +++++++++++++++++++++
5 files changed, 106 insertions(+), 7 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index d2763b0..4182a55 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -154,11 +154,19 @@ rte_eal_vdev_uninit(const char *name)

int rte_eal_dev_attach(const char *name, const char *devargs)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;
int ret = -1;

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_probe_one(&addr) < 0)
+ memset(&soc_addr, 0, sizeof(soc_addr));
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_probe_one(&soc_addr) < 0)
+ goto err_soc;
+
+ free(soc_addr.name);
+
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_probe_one(&pci_addr) < 0)
goto err;

} else {
@@ -168,6 +176,8 @@ int rte_eal_dev_attach(const char *name, const char *devargs)

return 0;

+err_soc:
+ free(soc_addr.name);
err:
RTE_LOG(ERR, EAL, "Driver, cannot attach the device\n");
return ret;
@@ -175,10 +185,17 @@ err:

int rte_eal_dev_detach(const char *name)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;
+
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_detach(&soc_addr) < 0)
+ goto soc_err;
+
+ free(soc_addr.name);

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_detach(&addr) < 0)
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_detach(&pci_addr) < 0)
goto err;
} else {
if (rte_eal_vdev_uninit(name))
@@ -186,6 +203,8 @@ int rte_eal_dev_detach(const char *name)
}
return 0;

+soc_err:
+ free(soc_addr.name);
err:
RTE_LOG(ERR, EAL, "Driver, cannot detach the device\n");
return -1;
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index 2bfe54a..5f6bcff 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -105,6 +105,13 @@ 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:
+ /* save target device name */
+ devargs->soc.addr.name = strdup(buf); /* FIXME: memory leak */
+ break;
+
case RTE_DEVTYPE_VIRTUAL:
/* save driver name */
ret = snprintf(devargs->virt.drv_name,
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index d8f0c00..3b885e8 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -37,6 +37,7 @@

#include <rte_log.h>
#include <rte_common.h>
+#include <rte_devargs.h>
#include <rte_soc.h>

#include "eal_private.h"
@@ -60,6 +61,21 @@ const char *soc_get_sysfs_path(void)
return path;
}

+static struct rte_devargs *soc_devargs_lookup(struct rte_soc_device *dev)
+{
+ struct rte_devargs *devargs;
+
+ TAILQ_FOREACH(devargs, &devargs_list, next) {
+ if (devargs->type != RTE_DEVTYPE_BLACKLISTED_SOC &&
+ devargs->type != RTE_DEVTYPE_WHITELISTED_SOC)
+ continue;
+ if (!rte_eal_compare_soc_addr(&dev->addr, &devargs->soc.addr))
+ return devargs;
+ }
+
+ return NULL;
+}
+
static int soc_id_match(const struct rte_soc_id *drv_id,
const struct rte_soc_id *dev_id)
{
@@ -96,6 +112,13 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
dev->addr.name);
RTE_LOG(DEBUG, EAL, " probe driver %s\n", dr->name);

+ if (dev->devargs != NULL
+ && dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC) {
+ RTE_LOG(DEBUG, EAL,
+ " device is blacklisted, skipping\n");
+ return 1;
+ }
+
dev->driver = dr;
RTE_VERIFY(dr->devinit != NULL);
return dr->devinit(dr, dev);
@@ -244,12 +267,26 @@ int
rte_eal_soc_probe(void)
{
struct rte_soc_device *dev = NULL;
+ struct rte_devargs *devargs;
int probe_all = 0;
int ret = 0;

+ if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_SOC) == 0)
+ probe_all = 1;
+
TAILQ_FOREACH(dev, &soc_device_list, next) {

- ret = soc_probe_all_drivers(dev);
+ /* set devargs in SoC structure */
+ devargs = soc_devargs_lookup(dev);
+ if (devargs != NULL)
+ dev->devargs = devargs;
+
+ /* probe all or only whitelisted devices */
+ if (probe_all)
+ ret = soc_probe_all_drivers(dev);
+ else if (devargs != NULL &&
+ devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ ret = soc_probe_all_drivers(dev);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Requested device %s"
" cannot be used\n", dev->addr.name);
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 53c59f5..757320e 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,11 @@ struct rte_devargs {
/** PCI location. */
struct rte_pci_addr addr;
} pci;
+ /** Used if type is RTE_DEVTYPE_*_SOC. */
+ 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
index 4117ffb..00fd0a6 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -72,6 +72,8 @@ struct rte_soc_addr {
char *fdt_path; /**< path to the associated node in FDT */
};

+struct rte_devargs;
+
/**
* A structure describing a SoC device.
*/
@@ -80,6 +82,7 @@ struct rte_soc_device {
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
struct rte_soc_driver *driver; /**< Associated driver */
+ struct rte_devargs *devargs; /**< Device user arguments */
};

struct rte_soc_driver;
@@ -141,6 +144,31 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,

return strcmp(a0->name, a1->name);
}
+
+/**
+ * Parse a specification of a soc device. The specification must differentiate
+ * a SoC device specification from the PCI bus and virtual devices. We assume
+ * a SoC specification starts with "soc:". The function allocates the name
+ * entry of the given addr.
+ *
+ * @return
+ * - 0 on success
+ * - 1 when not a SoC spec
+ * - -1 on failure
+ */
+static inline int
+rte_eal_parse_soc_spec(const char *spec, struct rte_soc_addr *addr)
+{
+ if (strstr(spec, "soc:") == spec) {
+ addr->name = strdup(spec + 4);
+ if (addr->name == NULL)
+ return -1;
+ return 0;
+ }
+
+ return 1;
+}
+
/**
* Scan for new SoC devices.
*/
--
2.8.0
Jan Viktorin
2016-05-06 13:47:55 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_soc.c | 5 +++++
lib/librte_eal/common/eal_private.h | 13 +++++++++++++
lib/librte_eal/linuxapp/eal/eal_soc.c | 11 +++++++++++
3 files changed, 29 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 3b885e8..75a7a97 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -242,6 +242,11 @@ rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
if (addr == NULL)
return -1;

+ /* update current SoC device in global list, kernel bindings might have
+ * changed since last time we looked at it */
+ if (soc_update_device(addr) < 0)
+ goto err_return;
+
TAILQ_FOREACH(dev, &soc_device_list, next) {
if (rte_eal_compare_soc_addr(&dev->addr, addr))
continue;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index b27ec89..fc1d9c6 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -197,6 +197,19 @@ struct rte_soc_device;
*/
int rte_eal_soc_init(void);

+/**
+ * Update a soc device object by asking the kernel for the latest information.
+ *
+ * This function is private to EAL.
+ *
+ * @param addr
+ * The SoC address to look for
+ * @return
+ * - 0 on success.
+ * - negative on error.
+ */
+int soc_update_device(const struct rte_soc_addr *addr);
+
struct rte_pci_driver;
struct rte_pci_device;

diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index a3b9935..742d80d 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -252,6 +252,17 @@ fail:
}

int
+soc_update_device(const struct rte_soc_addr *addr)
+{
+ char filename[PATH_MAX];
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ soc_get_sysfs_path(), addr->name);
+
+ return soc_scan_one(filename, addr->name);
+}
+
+int
rte_eal_soc_scan(void)
{
struct dirent *e;
--
2.8.0
Jan Viktorin
2016-05-06 13:47:56 UTC
Permalink
We reuse the existing infrastructure (rte_eal_get_kernel_driver_by_path) here
however another possible implementation is by parsing the uevent file.

As there are no well-known driver for SoC infra, we does not detect any. This
will be changed in the future by checking for VFIO and UIO drivers.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_soc.h | 2 ++
lib/librte_eal/linuxapp/eal/eal_soc.c | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 00fd0a6..206244a 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -53,6 +53,7 @@ extern "C" {

#include <rte_debug.h>
#include <rte_eal.h>
+#include <rte_dev.h>

TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */
@@ -83,6 +84,7 @@ struct rte_soc_device {
struct rte_soc_id *id; /**< SoC device ID list */
struct rte_soc_driver *driver; /**< Associated driver */
struct rte_devargs *devargs; /**< Device user arguments */
+ enum rte_kernel_driver kdrv; /**< Kernel driver */
};

struct rte_soc_driver;
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 742d80d..4f9070e 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -179,6 +179,30 @@ dev_content_free(struct rte_soc_device *dev)
dev->id = NULL;
}

+static int
+dev_setup_associated_driver(struct rte_soc_device *dev, const char *dirname)
+{
+ char filename[PATH_MAX];
+ char driver[PATH_MAX];
+ int ret;
+
+ /* parse driver */
+ snprintf(filename, sizeof(filename), "%s/driver", dirname);
+ ret = rte_eal_get_kernel_driver_by_path(filename, driver);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL, "Fail to get kernel driver for %s\n", dirname);
+ return 1;
+ }
+
+ if (!ret) {
+ dev->kdrv = RTE_KDRV_UNKNOWN;
+ } else {
+ dev->kdrv = RTE_KDRV_NONE;
+ }
+
+ return 0;
+}
+
/**
* Scan one SoC sysfs entry, and fill the devices list from it.
* We require to have the uevent file with records: OF_FULLNAME and
@@ -217,6 +241,9 @@ soc_scan_one(const char *dirname, const char *name)
goto fail;
free(uevent); /* not needed anymore */

+ if ((ret = dev_setup_associated_driver(dev, dirname)))
+ goto fail;
+
/* device is valid, add in list (sorted) */
if (TAILQ_EMPTY(&soc_device_list)) {
TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
@@ -231,6 +258,7 @@ soc_scan_one(const char *dirname, const char *name)
if (ret < 0) {
TAILQ_INSERT_BEFORE(dev2, dev, next);
} else { /* already registered */
+ dev2->kdrv = dev->kdrv;

dev_content_free(dev2);
dev2->addr.fdt_path = dev->addr.fdt_path;
--
2.8.0
Jan Viktorin
2016-05-06 13:47:57 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/bsdapp/eal/eal_soc.c | 12 ++++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 2 +
lib/librte_eal/common/eal_common_soc.c | 13 +++++++
lib/librte_eal/common/include/rte_soc.h | 50 +++++++++++++++++++++++++
lib/librte_eal/linuxapp/eal/eal_soc.c | 30 +++++++++++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 2 +
6 files changed, 109 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal_soc.c b/lib/librte_eal/bsdapp/eal/eal_soc.c
index f84aae9..687d37b 100644
--- a/lib/librte_eal/bsdapp/eal/eal_soc.c
+++ b/lib/librte_eal/bsdapp/eal/eal_soc.c
@@ -32,9 +32,21 @@
*/

#include <rte_soc.h>
+#include <rte_common.h>

int
rte_eal_soc_scan(void)
{
return 0;
}
+
+int
+rte_eal_soc_map_device(struct rte_soc_device *dev __rte_unused)
+{
+ return 0;
+}
+
+void
+rte_eal_soc_unmap_device(struct rte_soc_device *dev __rte_unused)
+{
+}
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index bd3dd11..b33282a 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -166,5 +166,7 @@ DPDK_16.07 {
rte_eal_soc_detach;
rte_eal_soc_probe;
rte_eal_soc_probe_one;
+ rte_eal_soc_map_device;
+ rte_eal_soc_unmap_device;

} DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 75a7a97..d0e5351 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -119,6 +119,11 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
return 1;
}

+ /* map resources */
+ ret = rte_eal_soc_map_device(dev);
+ if (ret)
+ return ret;
+
dev->driver = dr;
RTE_VERIFY(dr->devinit != NULL);
return dr->devinit(dr, dev);
@@ -168,6 +173,8 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *dr,
/* clear driver structure */
dev->driver = NULL;

+ /* unmap resources for devices */
+ rte_eal_soc_unmap_device(dev);
return 0;
}

@@ -313,6 +320,12 @@ soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
for (i = 0; dev->id && dev->id[i].compatible; ++i)
fprintf(f, " %s\n", dev->id[i].compatible);

+ for (i = 0; i < SOC_MAX_RESOURCE; i++) {
+ fprintf(f, " %16.16"PRIx64" %16.16"PRIx64"\n",
+ dev->mem_resource[i].phys_addr,
+ dev->mem_resource[i].len);
+ }
+
return 0;
}

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 206244a..3192121 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -50,6 +50,7 @@ extern "C" {
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
+#include <limits.h>

#include <rte_debug.h>
#include <rte_eal.h>
@@ -64,6 +65,14 @@ extern struct soc_device_list soc_device_list; /**< Global list of SoC devices.
/** Return SoC scan path of the sysfs root. */
const char *soc_get_sysfs_path(void);

+#define SOC_MAX_RESOURCE 6
+
+struct rte_soc_resource {
+ uint64_t phys_addr;
+ uint64_t len;
+ void *addr;
+};
+
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
};
@@ -82,6 +91,7 @@ struct rte_soc_device {
TAILQ_ENTRY(rte_soc_device) next; /**< Next probed SoC device */
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_resource mem_resource[SOC_MAX_RESOURCE];
struct rte_soc_driver *driver; /**< Associated driver */
struct rte_devargs *devargs; /**< Device user arguments */
enum rte_kernel_driver kdrv; /**< Kernel driver */
@@ -111,6 +121,34 @@ struct rte_soc_driver {
};

/**
+ * A structure describing a SoC mapping.
+ */
+struct soc_map {
+ void *addr;
+ char *path;
+ uint64_t offset;
+ uint64_t size;
+ uint64_t phaddr;
+};
+
+/**
+ * A structure describing a mapped SoC resource.
+ * For multi-process we need to reproduce all SoC mappings in secondary
+ * processes, so save them in a tailq.
+ */
+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];
+};
+
+/** mapped SoC resource list */
+TAILQ_HEAD(mapped_soc_res_list, mapped_soc_resource);
+
+/**
* Utility function to write a SoC device name, this device name can later be
* used to retrieve the corresponding rte_soc_addr using above functions.
*
@@ -202,6 +240,18 @@ int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
int rte_eal_soc_detach(const struct rte_soc_addr *addr);

/**
+ * Map SoC device resources into userspace.
+ *
+ * This is called by the EAL if (drv_flags & RTE_SOC_DRV_NEED_MAPPING).
+ */
+int rte_eal_soc_map_device(struct rte_soc_device *dev);
+
+/**
+ * Unmap the device resources.
+ */
+void rte_eal_soc_unmap_device(struct rte_soc_device *dev);
+
+/**
* Dump discovered SoC devices.
*/
void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 4f9070e..f57486a 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -47,6 +47,34 @@
#include "eal_internal_cfg.h"
#include "eal_private.h"

+int
+rte_eal_soc_map_device(struct rte_soc_device *dev)
+{
+ int ret = -1;
+
+ /* try mapping the NIC resources using VFIO if it exists */
+ switch (dev->kdrv) {
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+void
+rte_eal_soc_unmap_device(struct rte_soc_device *dev)
+{
+ switch (dev->kdrv) {
+ default:
+ RTE_LOG(DEBUG, EAL,
+ " Not managed by a supported kernel driver, skipped\n");
+ break;
+ }
+}
+
static char *
dev_read_uevent(const char *dirname)
{
@@ -259,6 +287,8 @@ soc_scan_one(const char *dirname, const char *name)
TAILQ_INSERT_BEFORE(dev2, dev, next);
} else { /* already registered */
dev2->kdrv = dev->kdrv;
+ memmove(dev2->mem_resource, dev->mem_resource,
+ sizeof(dev->mem_resource));

dev_content_free(dev2);
dev2->addr.fdt_path = dev->addr.fdt_path;
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 811cbf8..8e95a41 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -171,5 +171,7 @@ DPDK_16.07 {
rte_eal_soc_detach;
rte_eal_soc_probe;
rte_eal_soc_probe_one;
+ rte_eal_soc_map_device;
+ rte_eal_soc_unmap_device;

} DPDK_16.04;
--
2.8.0
Jan Viktorin
2016-05-06 13:47:58 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_soc.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 3192121..4b4789b 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -55,6 +55,7 @@ extern "C" {
#include <rte_debug.h>
#include <rte_eal.h>
#include <rte_dev.h>
+#include <rte_interrupts.h>

TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */
@@ -92,6 +93,7 @@ struct rte_soc_device {
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
struct rte_soc_resource mem_resource[SOC_MAX_RESOURCE];
+ struct rte_intr_handle intr_handle; /**< Interrupt handle */
struct rte_soc_driver *driver; /**< Associated driver */
struct rte_devargs *devargs; /**< Device user arguments */
enum rte_kernel_driver kdrv; /**< Kernel driver */
--
2.8.0
Jan Viktorin
2016-05-06 13:47:59 UTC
Permalink
The strict GCC rules do not allow to set the rte_soc_addr.compatible as it is
marked 'const'. However, we need it to be const because drivers will set it
statically by const strings. So this hack enables both.

Is there a better way to go?

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_soc.h | 6 ++-
lib/librte_eal/linuxapp/eal/eal_soc.c | 69 +++++++++++++++++++++++++++++++--
2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 4b4789b..830fcdc 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -75,7 +75,11 @@ struct rte_soc_resource {
};

struct rte_soc_id {
- const char *compatible; /**< OF compatible specification */
+ union {
+ /* workaround -Werror=discarded-qualifiers,cast-equal */
+ char *_compatible; /**< OF compatible specification */
+ const char *compatible; /**< OF compatible specification */
+ };
};

struct rte_soc_addr {
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index f57486a..c0e123a 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -173,6 +173,11 @@ static int
dev_parse_uevent(struct rte_soc_device *dev, const char *uevent)
{
const char *of;
+ const char *compat_n;
+ char *err;
+ long n;
+ char compat[strlen("OF_COMPATIBLE_NNNN=")];
+ long i;

of = dev_uevent_find(uevent, "OF_FULLNAME=");
if (of == NULL)
@@ -188,23 +193,81 @@ dev_parse_uevent(struct rte_soc_device *dev, const char *uevent)
RTE_LOG(DEBUG, EAL, "Detected device %s (%s)\n",
dev->addr.name, dev->addr.fdt_path);

- dev->id = calloc(1, sizeof(*dev->id));
+ compat_n = dev_uevent_find(uevent, "OF_COMPATIBLE_N=");
+ if (compat_n == NULL) {
+ RTE_LOG(ERR, EAL, "No OF_COMPATIBLE_N found\n");
+ return -1;
+ }
+
+ n = strtoul(compat_n, &err, 0);
+ if (*err != '\n' && err != NULL) {
+ RTE_LOG(ERR, EAL, "Failed to parse OF_COMPATIBLE_N: %.10s\n", err);
+ goto fail_fdt_path;
+ }
+
+ if (n == 0)
+ return 1; /* cannot match anything */
+ if (n > 9999) { /* match NNNN */
+ RTE_LOG(ERR, EAL, "OF_COMPATIBLE_N is invalid: %ld\n", n);
+ goto fail_fdt_path;
+ }
+
+ dev->id = calloc(n + 1, sizeof(*dev->id));
if (dev->id == NULL) {
+ RTE_LOG(ERR, PMD, "Failed to alloc memory for ID\n");
free(dev->addr.fdt_path);
return -1;
}

+ for (i = 0; i < n; ++i) {
+ snprintf(compat, sizeof(compat), "OF_COMPATIBLE_%lu=", i);
+ const char *val;
+
+ val = dev_uevent_find(uevent, compat);
+ if (val == NULL) {
+ RTE_LOG(ERR, EAL, "%s was not found\n", compat);
+ goto fail_id;
+ }
+
+ dev->id[i]._compatible = strdup_until_nl(val);
+ if (dev->id[i]._compatible == NULL) {
+ RTE_LOG(ERR, PMD,
+ "Failed to alloc memory for compatible\n");
+ goto fail_id;
+ }
+
+ RTE_LOG(DEBUG, EAL, " compatible: %s\n",
+ dev->id[i].compatible);
+ }
+
+ dev->id[n]._compatible = NULL; /* mark last one */
+
return 0;
+
+fail_id:
+ while (i-- >= 0)
+ free(dev->id[i]._compatible);
+ free(dev->id);
+fail_fdt_path:
+ free(dev->addr.fdt_path);
+ return -1;
}

static void
dev_content_free(struct rte_soc_device *dev)
{
+ int i;
+
if (dev->addr.fdt_path)
free(dev->addr.fdt_path);

- free(dev->id);
- dev->id = NULL;
+ if (dev->id != NULL) {
+ for (i = 0; dev->id[i]._compatible; ++i)
+ free(dev->id[i]._compatible);
+
+ free(dev->id);
+ dev->id = NULL;
+ }
}

static int
--
2.8.0
Jan Viktorin
2016-05-06 13:48:00 UTC
Permalink
No idea whether this is useful. Who creates the numa_node in the sysfs?
This can be probably dropped later.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_soc.c | 8 ++++----
lib/librte_eal/common/include/rte_soc.h | 1 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 26 ++++++++++++++++++++++++++
3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index d0e5351..af4daa5 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -108,8 +108,8 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
if (!soc_id_match(dr->id_table, dev->id))
return 1;

- RTE_LOG(DEBUG, EAL, "SoC device %s\n",
- dev->addr.name);
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %d\n",
+ dev->addr.name, dev->numa_node);
RTE_LOG(DEBUG, EAL, " probe driver %s\n", dr->name);

if (dev->devargs != NULL
@@ -162,8 +162,8 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *dr,
if (!soc_id_match(dr->id_table, dev->id))
return 1;

- RTE_LOG(DEBUG, EAL, "SoC device %s\n",
- dev->addr.name);
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %i\n",
+ dev->addr.name, dev->numa_node);

RTE_LOG(DEBUG, EAL, " remove driver: %s\n", dr->name);

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 830fcdc..49cfeb7 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -99,6 +99,7 @@ struct rte_soc_device {
struct rte_soc_resource mem_resource[SOC_MAX_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_kernel_driver kdrv; /**< Kernel driver */
};
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index c0e123a..6ef7d2f 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -45,6 +45,7 @@
#include <rte_soc.h>

#include "eal_internal_cfg.h"
+#include "eal_filesystem.h"
#include "eal_private.h"

int
@@ -294,6 +295,28 @@ dev_setup_associated_driver(struct rte_soc_device *dev, const char *dirname)
return 0;
}

+static int
+dev_setup_numa_node(struct rte_soc_device *dev, const char *dirname)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+ /* if no NUMA support, set default to 0 */
+ unsigned long tmp = 0;
+ int ret = 0;
+
+ /* get numa node */
+ snprintf(filename, sizeof(filename), "%s/numa_node", dirname);
+ if ((f = fopen(filename, "r")) != NULL) {
+ if (eal_parse_sysfs_valuef(f, &tmp) < 0)
+ ret = 1;
+
+ fclose(f);
+ }
+
+ dev->numa_node = tmp;
+ return ret;
+}
+
/**
* Scan one SoC sysfs entry, and fill the devices list from it.
* We require to have the uevent file with records: OF_FULLNAME and
@@ -335,6 +358,9 @@ soc_scan_one(const char *dirname, const char *name)
if ((ret = dev_setup_associated_driver(dev, dirname)))
goto fail;

+ if ((ret = dev_setup_numa_node(dev, dirname)) < 0)
+ goto fail;
+
/* device is valid, add in list (sorted) */
if (TAILQ_EMPTY(&soc_device_list)) {
TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
--
2.8.0
Jan Viktorin
2016-05-06 13:48:01 UTC
Permalink
The flags are copied from the PCI ones. They should be refactorized into a
general set of flags in the future.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_soc.h | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 49cfeb7..50a3b35 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -125,8 +125,18 @@ struct rte_soc_driver {
soc_devinit_t *devinit; /**< Device initialization */
soc_devuninit_t *devuninit; /**< Device uninitialization */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+ uint32_t drv_flags; /**< Control handling of device */
};

+/** Device needs to map its resources by EAL */
+#define RTE_SOC_DRV_NEED_MAPPING 0x0001
+/** Device needs to be unbound event if no module is provieded */
+#define RTE_SOC_DRV_FORCE_UNBIND 0x0004
+/** Device driver supports link state interrupt */
+#define RTE_SOC_DRV_INTR_LSC 0x0008
+/** Device driver supports detaching capability */
+#define RTE_SOC_DRV_DETACHABLE 0x0010
+
/**
* A structure describing a SoC mapping.
*/
--
2.8.0
Shreyansh Jain
2016-06-13 14:21:40 UTC
Permalink
-----Original Message-----
Sent: Friday, May 06, 2016 7:18 PM
Subject: [dpdk-dev] [PATCH v1 19/28] eal/soc: add drv_flags
The flags are copied from the PCI ones. They should be refactorized into a
general set of flags in the future.
---
lib/librte_eal/common/include/rte_soc.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/lib/librte_eal/common/include/rte_soc.h
b/lib/librte_eal/common/include/rte_soc.h
index 49cfeb7..50a3b35 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -125,8 +125,18 @@ struct rte_soc_driver {
soc_devinit_t *devinit; /**< Device initialization */
soc_devuninit_t *devuninit; /**< Device uninitialization */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+ uint32_t drv_flags; /**< Control handling of device */
};
+/** Device needs to map its resources by EAL */
+#define RTE_SOC_DRV_NEED_MAPPING 0x0001
+/** Device needs to be unbound event if no module is provieded */
Comment should read "Device needs to be unbound even if no module is provided"
+#define RTE_SOC_DRV_FORCE_UNBIND 0x0004
+/** Device driver supports link state interrupt */
+#define RTE_SOC_DRV_INTR_LSC 0x0008
+/** Device driver supports detaching capability */
+#define RTE_SOC_DRV_DETACHABLE 0x0010
+
/**
* A structure describing a SoC mapping.
*/
--
2.8.0
Jan Viktorin
2016-06-13 14:26:10 UTC
Permalink
On Mon, 13 Jun 2016 14:21:40 +0000
Post by Shreyansh Jain
-----Original Message-----
Sent: Friday, May 06, 2016 7:18 PM
Subject: [dpdk-dev] [PATCH v1 19/28] eal/soc: add drv_flags
The flags are copied from the PCI ones. They should be refactorized into a
general set of flags in the future.
---
lib/librte_eal/common/include/rte_soc.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/lib/librte_eal/common/include/rte_soc.h
b/lib/librte_eal/common/include/rte_soc.h
index 49cfeb7..50a3b35 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -125,8 +125,18 @@ struct rte_soc_driver {
soc_devinit_t *devinit; /**< Device initialization */
soc_devuninit_t *devuninit; /**< Device uninitialization */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+ uint32_t drv_flags; /**< Control handling of device */
};
+/** Device needs to map its resources by EAL */
+#define RTE_SOC_DRV_NEED_MAPPING 0x0001
+/** Device needs to be unbound event if no module is provieded */
Comment should read "Device needs to be unbound even if no module is provided"
OK, thanks.
Post by Shreyansh Jain
+#define RTE_SOC_DRV_FORCE_UNBIND 0x0004
+/** Device driver supports link state interrupt */
+#define RTE_SOC_DRV_INTR_LSC 0x0008
+/** Device driver supports detaching capability */
+#define RTE_SOC_DRV_DETACHABLE 0x0010
+
/**
* A structure describing a SoC mapping.
*/
--
2.8.0
Jan Viktorin
2016-05-06 13:48:02 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_soc.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index af4daa5..d178c48 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -119,10 +119,12 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
return 1;
}

- /* map resources */
- ret = rte_eal_soc_map_device(dev);
- if (ret)
- return ret;
+ if (dr->drv_flags & RTE_SOC_DRV_NEED_MAPPING) {
+ /* map resources */
+ ret = rte_eal_soc_map_device(dev);
+ if (ret)
+ return ret;
+ }

dev->driver = dr;
RTE_VERIFY(dr->devinit != NULL);
@@ -173,8 +175,10 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *dr,
/* clear driver structure */
dev->driver = NULL;

- /* unmap resources for devices */
- rte_eal_soc_unmap_device(dev);
+ if (dr->drv_flags & RTE_SOC_DRV_NEED_MAPPING)
+ /* unmap resources for devices */
+ rte_eal_soc_unmap_device(dev);
+
return 0;
}
--
2.8.0
Jan Viktorin
2016-05-06 13:48:03 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/eal_common_soc.c | 6 ++++++
lib/librte_eal/common/eal_private.h | 10 ++++++++++
lib/librte_eal/linuxapp/eal/eal_soc.c | 11 +++++++++++
3 files changed, 27 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index d178c48..49dbcb8 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -38,6 +38,7 @@
#include <rte_log.h>
#include <rte_common.h>
#include <rte_devargs.h>
+#include <rte_eal.h>
#include <rte_soc.h>

#include "eal_private.h"
@@ -124,6 +125,11 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
ret = rte_eal_soc_map_device(dev);
if (ret)
return ret;
+ } else if (dr->drv_flags & RTE_SOC_DRV_FORCE_UNBIND
+ && rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ /* unbind */
+ if (soc_unbind_kernel_driver(dev) < 0)
+ return -1;
}

dev->driver = dr;
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index fc1d9c6..f1409cf 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -210,6 +210,16 @@ int rte_eal_soc_init(void);
*/
int soc_update_device(const struct rte_soc_addr *addr);

+/**
+ * Unbind kernel driver for this device
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ * 0 on success, negative on error
+ */
+int soc_unbind_kernel_driver(struct rte_soc_device *dev);
+
struct rte_pci_driver;
struct rte_pci_device;

diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 6ef7d2f..6e9e242 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -49,6 +49,17 @@
#include "eal_private.h"

int
+soc_unbind_kernel_driver(struct rte_soc_device *dev)
+{
+ char devpath[PATH_MAX];
+
+ snprintf(devpath, sizeof(devpath), "%s/%s",
+ soc_get_sysfs_path(), dev->addr.name);
+
+ return rte_eal_unbind_kernel_driver(devpath, dev->addr.name);
+}
+
+int
rte_eal_soc_map_device(struct rte_soc_device *dev)
{
int ret = -1;
--
2.8.0
Jan Viktorin
2016-05-06 13:48:04 UTC
Permalink
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 <***@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
Jan Viktorin
2016-05-06 13:48:05 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_eal/common/include/rte_common.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index 332f2a4..a9b6792 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -322,6 +322,22 @@ rte_bsf32(uint32_t v)
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
#endif

+/**
+ * Return pointer to the wrapping struct instance.
+ * Example:
+ *
+ * struct wrapper {
+ * ...
+ * struct child c;
+ * ...
+ * };
+ *
+ * struct child *x = obtain(...);
+ * struct wrapper *w = container_of(x, struct wrapper, c);
+ */
+#define container_of(p, type, member) \
+ ((type *) (((char *) (p)) - offsetof(type, member)))
+
#define _RTE_STR(x) #x
/** Take a macro value and get a string version of it */
#define RTE_STR(x) _RTE_STR(x)
--
2.8.0
Jan Viktorin
2016-05-06 13:48:06 UTC
Permalink
It is not necessary to place the rte_pci_driver at the beginning
of the rte_eth_dev struct anymore as we use the container_of macro
to get the parent pointer.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_ether/rte_ethdev.c | 4 ++--
lib/librte_ether/rte_ethdev.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 55b32da..5474523 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -236,7 +236,7 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,

int diag;

- eth_drv = (struct eth_driver *)pci_drv;
+ eth_drv = container_of(pci_drv, struct eth_driver, pci_drv);

rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
sizeof(ethdev_name));
@@ -297,7 +297,7 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
if (eth_dev == NULL)
return -ENODEV;

- eth_drv = (const struct eth_driver *)pci_dev->driver;
+ eth_drv = container_of(pci_dev->driver, struct eth_driver, pci_drv);

/* Invoke PMD device uninit function */
if (*eth_drv->eth_dev_uninit) {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index c8cbe17..622c9d8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1813,7 +1813,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
* Each Ethernet driver acts as a PCI driver and is represented by a generic
* *eth_driver* structure that holds:
*
- * - An *rte_pci_driver* structure (which must be the first field).
+ * - An *rte_pci_driver* structure.
*
* - The *eth_dev_init* function invoked for each matching PCI device.
*
--
2.8.0
Jan Viktorin
2016-05-06 13:48:07 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_ether/rte_ethdev.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 5474523..0b0dcbc 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3077,6 +3077,8 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
return;
}

+ RTE_VERIFY(eth_dev->pci_dev != NULL);
+
eth_dev->data->dev_flags = 0;
if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
--
2.8.0
Jan Viktorin
2016-05-06 13:48:08 UTC
Permalink
We abstract access to the intr_handle here as we want to get
it either from the pci_dev or soc_dev.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_ether/rte_ethdev.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 0b0dcbc..9378a4a 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2404,6 +2404,17 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}

+static inline
+struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return &dev->pci_dev->intr_handle;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
{
@@ -2419,7 +2430,7 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
}

dev = &rte_eth_devices[port_id];
- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
@@ -2482,7 +2493,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
return -EINVAL;
}

- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
--
2.8.0
Jan Viktorin
2016-05-06 13:48:09 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_ether/rte_ethdev.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 9378a4a..4af2e5f 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2449,6 +2449,17 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
return 0;
}

+static inline
+const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return dev->driver->pci_drv.name;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
const struct rte_memzone *
rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
uint16_t queue_id, size_t size, unsigned align,
@@ -2456,9 +2467,11 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
{
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
+ const char *drv_name;

+ drv_name = eth_dev_get_driver_name(dev);
snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
- dev->driver->pci_drv.name, ring_name,
+ drv_name, ring_name,
dev->data->port_id, queue_id);

mz = rte_memzone_lookup(z_name);
--
2.8.0
Jan Viktorin
2016-05-06 13:48:10 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
---
lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
lib/librte_ether/rte_ethdev.h | 31 +++++++++++
2 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4af2e5f..9259c2c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}

int
+rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+ int diag;
+
+ eth_drv = container_of(soc_drv, struct eth_driver, soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocate(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENOMEM;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev->data->dev_private = rte_zmalloc("ethdev private structure",
+ eth_drv->dev_private_size,
+ RTE_CACHE_LINE_SIZE);
+ if (eth_dev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private port data\n");
+ }
+ eth_dev->soc_dev = soc_dev;
+ eth_dev->driver = eth_drv;
+ eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+ /*
+ * Set the default MTU.
+ */
+ eth_dev->data->mtu = ETHER_MTU;
+
+ /* Invoke PMD device initialization function */
+ diag = (*eth_drv->eth_dev_init)(eth_dev);
+ if (diag == 0)
+ return 0;
+
+ RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n",
+ soc_drv->name,
+ soc_dev->id.name);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+ rte_eth_dev_release_port(eth_dev);
+ return diag;
+}
+
+int
+rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocated(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENODEV;
+
+ eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv);
+
+ /* Invoke PMD device uninit function */
+ if (*eth_drv->eth_dev_uninit) {
+ ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+ if (ret)
+ return ret;
+ }
+
+ /* free ether device */
+ rte_eth_dev_release_port(eth_dev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ eth_dev->soc_dev = NULL;
+ eth_dev->driver = NULL;
+ eth_dev->data = NULL;
+
+ return 0;
+}
+
+
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)

RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
dev_info->driver_name = dev->data->drv_name;
}

@@ -2408,8 +2501,13 @@ static inline
struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return &dev->pci_dev->intr_handle;
}
+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return &dev->soc_dev->intr_handle;
+ }

RTE_VERIFY(0);
return NULL;
@@ -2453,8 +2551,13 @@ static inline
const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return dev->driver->pci_drv.name;
}
+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return dev->driver->soc_drv.name;
+ }

RTE_VERIFY(0);
return NULL;
@@ -3114,6 +3217,28 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
eth_dev->data->drv_name = pci_dev->driver->name;
}

+void
+rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev, struct rte_soc_device *soc_dev)
+{
+ if ((eth_dev == NULL) || (soc_dev == NULL)) {
+ RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n",
+ eth_dev, soc_dev);
+ return;
+ }
+
+ RTE_VERIFY(eth_dev->soc_dev != NULL);
+
+ eth_dev->data->dev_flags = 0;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+ eth_dev->data->kdrv = soc_dev->kdrv;
+ eth_dev->data->numa_node = soc_dev->numa_node;
+ eth_dev->data->drv_name = soc_dev->driver->name;
+}
+
int
rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
struct rte_eth_l2_tunnel_conf *l2_tunnel)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 622c9d8..9ecc3b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -180,6 +180,7 @@ extern "C" {
#include <rte_log.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include "rte_ether.h"
@@ -855,6 +856,7 @@ struct rte_eth_conf {
*/
struct rte_eth_dev_info {
struct rte_pci_device *pci_dev; /**< Device PCI information. */
+ struct rte_soc_device *soc_dev; /**< Device SoC information. */
const char *driver_name; /**< Device Driver name. */
unsigned int if_index; /**< Index to bound host interface, or 0 if none.
Use if_indextoname() to translate into an interface name. */
@@ -1590,6 +1592,7 @@ struct rte_eth_dev {
const struct eth_driver *driver;/**< Driver for this device */
const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */
/** User application callbacks for NIC interrupts */
struct rte_eth_dev_cb_list link_intr_cbs;
/**
@@ -1823,6 +1826,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
*/
struct eth_driver {
struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is also a SoC driver. */
eth_dev_init_t eth_dev_init; /**< Device init function. */
eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */
unsigned int dev_private_size; /**< Size of device private data. */
@@ -4158,6 +4162,20 @@ void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
struct rte_pci_device *pci_dev);

/**
+ * Copy SoC device info to the Ethernet device data.
+ *
+ * @param eth_dev
+ * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
+ * @param soc_dev
+ * The *soc_dev* pointer is the address of the *rte_soc_device* structure.
+ *
+ * @return
+ * - 0 on success, negative on error
+ */
+void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev);
+
+/**
* Create memzone for HW rings.
* malloc can't be used as the physical address is needed.
* If the memzone is already created, then this function returns a ptr
@@ -4241,6 +4259,19 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev);
+
#ifdef __cplusplus
}
#endif
--
2.8.0
Shreyansh jain
2016-06-29 09:42:07 UTC
Permalink
Hi Jan,
Post by Jan Viktorin
---
lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
lib/librte_ether/rte_ethdev.h | 31 +++++++++++
2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4af2e5f..9259c2c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}
[...]
Post by Jan Viktorin
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Post by Jan Viktorin
dev_info->driver_name = dev->data->drv_name;
}
[...]

-
Shreyansh
Jan Viktorin
2016-07-04 13:04:51 UTC
Permalink
On Wed, 29 Jun 2016 15:12:07 +0530
Post by Shreyansh Jain
Hi Jan,
Post by Jan Viktorin
---
lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
lib/librte_ether/rte_ethdev.h | 31 +++++++++++
2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4af2e5f..9259c2c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}
[...]
Post by Jan Viktorin
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.

Jan
Post by Shreyansh Jain
Post by Jan Viktorin
dev_info->driver_name = dev->data->drv_name;
}
[...]
-
Shreyansh
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Shreyansh jain
2016-07-04 14:27:18 UTC
Permalink
Post by Jan Viktorin
On Wed, 29 Jun 2016 15:12:07 +0530
Post by Shreyansh Jain
Hi Jan,
Post by Jan Viktorin
---
lib/librte_ether/rte_ethdev.c | 127 +++++++++++++++++++++++++++++++++++++++++-
lib/librte_ether/rte_ethdev.h | 31 +++++++++++
2 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4af2e5f..9259c2c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -320,6 +320,99 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}
[...]
Post by Jan Viktorin
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
Post by Jan Viktorin
Jan
Post by Shreyansh Jain
Post by Jan Viktorin
dev_info->driver_name = dev->data->drv_name;
}
[...]
-
Shreyansh
-
Shreyansh
Jan Viktorin
2016-07-04 14:36:46 UTC
Permalink
On Mon, 4 Jul 2016 19:57:18 +0530
Shreyansh jain <***@nxp.com> wrote:

[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
Post by Jan Viktorin
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...

Jan
Shreyansh jain
2016-07-05 04:42:38 UTC
Permalink
Post by Jan Viktorin
On Mon, 4 Jul 2016 19:57:18 +0530
[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
Post by Jan Viktorin
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).

Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.
Post by Jan Viktorin
Jan
-
Shreyansh
Jan Viktorin
2016-07-05 05:16:30 UTC
Permalink
Hello Shreyansh,

Post by Shreyansh jain
Post by Jan Viktorin
On Mon, 4 Jul 2016 19:57:18 +0530
[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
@@ -1431,7 +1524,7 @@ >rte_eth_dev_info_get(uint8_t port_id, struct >rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->>dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).
‎>
Post by Shreyansh jain
Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.
Ok. I am away for few days this week but I will continue as soon as possible on the soc patchset and also on the rte_device/driver issue. We have to cut this as soon as possible. I think the best would be to post a small patchset on top of this one introducing the change.

I think, there should be a single list of rte_device and a list for rte_driver while preserving lists for each infra, so also rte_pci_device would have a separate list. Then, it's possible to iterate over all PCI devices easily and iterate over all devices generically at the same time.

What I am not sure about are addr and id things. It's quite difficult to generalize them. The addr needs a conpare function but how to compare pci addr to another type of addr? Do we need this? If so, I'll work on this.

Another thing - resources. Do we want to have a kind of a generic rte_resource instead of rte_pci_resource? I think this is clearly possible. I am about to do this.

I am afraid we are unable to change devargs significantly in this release :/ (due to time and lack of a discussion here).‎ What I really like to see is the virtual device conversion and pmd_type removal. Are you able to look at this?

Any other objections?

Jan Viktorin
RehiveTech
Sent from a mobile device‎
Post by Shreyansh jain
Post by Jan Viktorin
Jan
 
-
Shreyansh
Shreyansh jain
2016-07-07 10:29:41 UTC
Permalink
Hi Jan,

Apologies for delay in my response.
Post by Jan Viktorin
Hello Shreyansh,

Post by Shreyansh jain
Post by Jan Viktorin
On Mon, 4 Jul 2016 19:57:18 +0530
[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
@@ -1431,7 +1524,7 @@ >rte_eth_dev_info_get(uint8_t port_id, struct >rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->>dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
Really? Then probably I understood it wrong. I don't have any issues with the first one as well but just for slightly cleaner approach I thought of going with your suggest (or, suggestion as understood by me).
‎>
Post by Shreyansh jain
Anyways the patch is broken and doesn't apply on master. I will push a new version (with revert EAL_PCI_REGISTER arguments) within today.
Ok. I am away for few days this week but I will continue as soon as possible on the soc patchset and also on the rte_device/driver issue. We have to cut this as soon as possible. I think the best would be to post a small patchset on top of this one introducing the change.
I am anyway working on a driver for NXP's SoC platform which I am basing over rte_device + SoC patchset.
I plan to release a draft of this driver soon. It might help validate both the patchsets in a limited manner.
Post by Jan Viktorin
I think, there should be a single list of rte_device and a list for rte_driver while preserving lists for each infra, so also rte_pci_device would have a separate list. Then, it's possible to iterate over all PCI devices easily and iterate over all devices generically at the same time.
I have similar understanding. Separate pci/soc lists, and unified rte_driver and rte_device lists. This, in my opinion, would help keep the interfaces clean (free of unnecessary checks).
Post by Jan Viktorin
What I am not sure about are addr and id things. It's quite difficult to generalize them. The addr needs a conpare function but how to compare pci addr to another type of addr? Do we need this? If so, I'll work on this.
I am not sure why we need to compare the PCI addresses with non-PCI (or any other, SoC) address set? Can you elaborate?
Post by Jan Viktorin
Another thing - resources. Do we want to have a kind of a generic rte_resource instead of rte_pci_resource? I think this is clearly possible. I am about to do this.
The idea sounds good but I don't know whether it would be feasible or not. My understanding is that resources have special characteristics. Generalizing them would involve creating opaque objects in rte_resource{..} which in turn beats the purpose of generalization.

Probably, I will wait for your next patchset version to understand your approach.
Post by Jan Viktorin
I am afraid we are unable to change devargs significantly in this release :/ (due to time and lack of a discussion here).‎ What I really like to see is the virtual device conversion and pmd_type removal. Are you able to look at this?
pmd_type removal is my todo as well. This would anyway impact the vdevs.
I haven't given devargs much thought, yet.
Post by Jan Viktorin
Any other objections?
I was looking at various discussions [1],[2] that have happened in past. From that, the summary I have is:
1) Generalize devices to rte_device/rte_driver
`-- Cleaner interfaces/difference for 'bus', 'driver' and 'device'
`-- Moving the init/deinit functions into rte_device/rte_driver layer
`-- hierarchical device structure (as explained by David in [1])
2) Do away with device type specific initializations (registrations)
`-- No more pdev/vdev distinction
`-- standardizing devargs for accepting device specific strings.
3) Hotplug support

Most of work of (1) David has already done. What remains is completing (2) and probably (3) which I haven't verified yet.

[1] http://dpdk.org/ml/archives/dev/2016-January/031390.html
[2] http://dpdk.org/ml/archives/dev/2016-January/030975.html
Post by Jan Viktorin
Jan Viktorin
RehiveTech
Sent from a mobile device‎
Post by Shreyansh jain
Post by Jan Viktorin
Jan
-
Shreyansh
-
Shreyansh
Shreyansh jain
2016-07-12 08:45:17 UTC
Permalink
Hi Jan,
Post by Jan Viktorin
On Mon, 4 Jul 2016 19:57:18 +0530
[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
Post by Jan Viktorin
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
I have sent across a v6 of the rte_device/driver change set.
Can you see if that is in-line with your expectations as well as the series [1] posted by you recently?
I was making changes for vdev but for now I have ignored them as your series already includes those changes.

I used your patches and based them over the v6 rte_device patchset - besides some minor conflicts, its seems to merge fine.

[1] http://dpdk.org/ml/archives/dev/2016-July/043645.html
Post by Jan Viktorin
Jan
-
Shreyansh
Jan Viktorin
2016-07-12 10:41:39 UTC
Permalink
On Tue, 12 Jul 2016 14:15:17 +0530
Post by Shreyansh Jain
Hi Jan,
Post by Jan Viktorin
On Mon, 4 Jul 2016 19:57:18 +0530
[...]
Post by Shreyansh jain
Post by Jan Viktorin
Post by Shreyansh jain
Post by Jan Viktorin
@@ -1431,7 +1524,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
- dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
I think both the members, pci_dev and soc_dev, should be updated by this call.
Is there some specific reason why soc_dev is the only one which is getting updated?
Yes, looks like a mistake. Thanks! And sorry for delayed reply.
No problems - thanks for confirmation.
I have gone through almost complete series and as and when you rebase it, it would have my ACK.
OK, thanks. That's what I am playing with right now. I've rebased on v3 of this patch. There will
be some more tests in my v2.
Post by Shreyansh jain
rte_driver patchset which I sent last are broken - I will publish an updated version very soon.
I am surprised that you've changed the args to RTE_EAL_PCI_REGISTER... Are you sure about this step?
I wrote that I'll change it myself for v2 for SoC to accept name and pointer as it was originally for PCI...
I have sent across a v6 of the rte_device/driver change set.
Can you see if that is in-line with your expectations as well as the series [1] posted by you recently?
I was making changes for vdev but for now I have ignored them as your series already includes those changes.
I used your patches and based them over the v6 rte_device patchset - besides some minor conflicts, its seems to merge fine.
[1] http://dpdk.org/ml/archives/dev/2016-July/043645.html
I will check it as soon as possible. Thanks.

Jan
Post by Shreyansh Jain
Post by Jan Viktorin
Jan
-
Shreyansh
--
Jan Viktorin E-mail: ***@RehiveTech.com
System Architect Web: www.RehiveTech.com
RehiveTech
Brno, Czech Republic
Shreyansh Jain
2016-08-31 11:00:21 UTC
Permalink
Introduction:
=============

This patch set is direct derivative of Jan's original series [1],[2].
(Confirmed offline with Jan before posting.)

- As this deviates substantially from original series, if need be I can
post it as a separate patch rather than v2. Please suggest.
- Also, there are comments on original v1 ([4]) which are _not_
incorporated in this series as they refer to section no more in new
version.
- Initial set also contains certain patches to generalize some PCI specific
structures and function to common EAL ([6,7,8,9]. Those patches I'll post
separately as they are good changes (in my opinion) and not related to
SoC framework.

It is built over the series [3] which introduces device structures for
rte_driver/rte_device for generalizing devices into PCI, VDEV, XXX. For
the purpose of this patchset, XXX=>SOC.

Aim:
====

As of now EAL is primarly focused on PCI initialization/probing.

rte_eal_init()
|- rte_eal_pci_init(): Find PCI devices from sysfs
|- ...
|- rte_eal_memzone_init()
|- ...
`- rte_eal_pci_probe(): Driver<=>Device initialization

This patchset introduces SoC framework which would enable SoC drivers and
drivers to be plugged into EAL, very similar to how PCI drivers/devices are
done today.

This is a stripped down version of PCI framework which allows the SoC PMDs
to implement their own routines for detecting devices and linking devices to
drivers.

1) Changes to EAL
rte_eal_init()
|- rte_eal_pci_init(): Find PCI devices from sysfs
|- rte_eal_soc_init(): Calls PMDs->scan_fn
|- ...
|- rte_eal_memzone_init()
|- ...
|- rte_eal_pci_probe(): Driver<=>Device initialization, PMD->devinit()
`- rte_eal_soc_probe(): Calls PMDs->match_fn and PMDs->devinit();

2) New device/driver structures:
- rte_soc_driver (inheriting rte_driver)
- rte_soc_device (inheriting rte_device)
- rte_eth_dev and eth_driver embedded rte_soc_device and rte_soc_driver,
respectively.

3) The SoC PMDs need to:
- define rte_soc_driver with necessary scan and match callbacks
- Register themselves using DRIVER_REGISTER_SOC()
- Implement respective bus scanning in the scan callbacks to add necessary
devices to SoC device list
- Implement necessary eth_dev_init/uninint for ethernet instances

4) Design considerations that are same as PCI:
- SoC initialization is being done through rte_eal_init(), just after PCI
initialization is done.
- As in case of PCI, probe is done after rte_eal_pci_probe() to link the
devices detected with the drivers registered.
- Device attach/detach functions are available and have been designed on
the lines of PCI framework.
- PMDs register using DRIVER_REGISTER_SOC, very similar to
DRIVER_REGISTER_PCI for PCI devices.
- Linked list of SoC driver and devices exists independent of the other
driver/device list, but inheriting rte_driver/rte_driver, these are also
part of a global list.

5) Design considerations that are different from PCI:
- Each driver implements its own scan and match function. PCI uses the BDF
format to read the device from sysfs, but this _may_not_ be a case for a
SoC ethernet device.
= This is an important change from initial proposal by Jan in [2]. Unlike
his attempt to use /sys/bus/platform, this patch relies on the PMD to
detect the devices. This is because SoC may require specific or
additional info for device detection. Further, SoC may have embedded
devices/MACs which require initialization which cannot be covered through
sysfs parsing.
= PCI based PMDs rely on EAL's capability to detect devices. This
proposal puts the onus on PMD to detect devices, add to soc_device_list
and wait for Probe. Matching, of device<=>driver is again PMD's callback.

Patchset Overview:
==================
- Patches 0001~0003 introduce the base infrastructure and test case
- Patch 0004 is for command line support for no-soc, on lines of no-pci
- Patch 0005 enables EAL to handle SoC type devices
- Patch 0006 adds support for scan and probe callbacks and updates the test
framework with relevant test case.
- Patch 0007~0009 enable device argument, driver specific flags and
interrupt handling related basic infra. Subsequent patches build up on
them.
- Patch 0010~0013 makes changes to PCI as well as ethdev code to remove
assumption that eth_driver is a PCI driver.
- Patch 0014 adds necessary ethdev probe/remove functions for PMDs to use

Future/Pending Changes:
=======================
- Device whitelisting/blacklist still relies on command line '-b' and '-c'
which are internally implemented using OPT_PCI_BLACKLIST/OPT_PCI_WHITELIST.
This needs to be changed to a generic form - OPT_DEV_*LIST - probably.

[1] http://dpdk.org/ml/archives/dev/2016-January/030915.html
[2] http://www.dpdk.org/ml/archives/dev/2016-May/038486.html
[3] http://dpdk.org/ml/archives/dev/2016-August/045707.html
[4] http://dpdk.org/ml/archives/dev/2016-May/038948.html
[5] http://dpdk.org/ml/archives/dev/2016-May/038953.html
[6] http://dpdk.org/ml/archives/dev/2016-May/038487.html
[7] http://dpdk.org/ml/archives/dev/2016-May/038488.html
[8] http://dpdk.org/ml/archives/dev/2016-May/038489.html
[9] http://dpdk.org/ml/archives/dev/2016-May/038491.html

Change since v1: [2]
- Removed patch 1-5 which were for generalizing some PCI specific routines
into EAL. These patches are good-to-have but not directly linked to SoC
and hence would be proposed separately.
- Removed support for sysfs parsing (patches 6~9)
- Rebasing over the recent (v8) version of rte_driver/device patchset
- Rebasing over master (16.07)
- Changes to various map file to change API intro to 16.11 from 16.07

Shreyansh Jain (14):
eal/soc: introduce very essential SoC infra definitions
eal/soc: add rte_eal_soc_register/unregister logic
eal/soc: Implement SoC device list and dump
eal: introduce --no-soc option
eal/soc: init SoC infra from EAL
eal/soc: implement probing of drivers
eal/soc: extend and utilize devargs
eal/soc: add drv_flags
eal/soc: add intr_handle
ether: utilize container_of for pci_drv
ether: verify we copy info from a PCI device
ether: extract function eth_dev_get_intr_handle
ether: extract function eth_dev_get_driver_name
ether: Support rte_soc_driver/device for etherdev

app/test/Makefile | 1 +
app/test/test_soc.c | 337 ++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/eal.c | 4 +
lib/librte_eal/bsdapp/eal/eal_soc.c | 46 ++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 9 +
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_common_dev.c | 27 +-
lib/librte_eal/common/eal_common_devargs.c | 17 ++
lib/librte_eal/common/eal_common_options.c | 5 +
lib/librte_eal/common/eal_common_soc.c | 326 +++++++++++++++++++++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 +
lib/librte_eal/common/eal_private.h | 14 +
lib/librte_eal/common/include/rte_devargs.h | 8 +
lib/librte_eal/common/include/rte_soc.h | 246 +++++++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/linuxapp/eal/eal.c | 8 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 72 +++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 8 +
lib/librte_ether/rte_ethdev.c | 165 +++++++++++-
lib/librte_ether/rte_ethdev.h | 33 ++-
22 files changed, 1320 insertions(+), 14 deletions(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/common/eal_common_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:22 UTC
Permalink
Define initial structures and functions for the SoC infrastructure.
This patch supports only a very minimal functions for now.
More features will be added in the following commits.

Includes rte_device/rte_driver inheritance of
rte_soc_device/rte_soc_driver.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/Makefile | 1 +
app/test/test_soc.c | 90 +++++++++++++++++++++
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_private.h | 4 +
lib/librte_eal/common/include/rte_soc.h | 138 ++++++++++++++++++++++++++++++++
5 files changed, 234 insertions(+), 1 deletion(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h

diff --git a/app/test/Makefile b/app/test/Makefile
index 611d77a..64b261d 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -77,6 +77,7 @@ APP = test
#
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
SRCS-y += test.c
+SRCS-y += test_soc.c
SRCS-y += resource.c
SRCS-y += test_resource.c
test_resource.res: test_resource.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
new file mode 100644
index 0000000..916a863
--- /dev/null
+++ b/app/test/test_soc.c
@@ -0,0 +1,90 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_soc.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+static char *safe_strdup(const char *s)
+{
+ char *c = strdup(s);
+
+ if (c == NULL)
+ rte_panic("failed to strdup '%s'\n", s);
+
+ return c;
+}
+
+static int test_compare_addr(void)
+{
+ struct rte_soc_addr a0;
+ struct rte_soc_addr a1;
+ struct rte_soc_addr a2;
+
+ a0.name = safe_strdup("ethernet0");
+ a0.fdt_path = NULL;
+
+ a1.name = safe_strdup("ethernet0");
+ a1.fdt_path = NULL;
+
+ a2.name = safe_strdup("ethernet1");
+ a2.fdt_path = NULL;
+
+ TEST_ASSERT(!rte_eal_compare_soc_addr(&a0, &a1),
+ "Failed to compare two soc addresses that equal");
+ TEST_ASSERT(rte_eal_compare_soc_addr(&a0, &a2),
+ "Failed to compare two soc addresses that differs");
+
+ free(a2.name);
+ free(a1.name);
+ free(a0.name);
+ return 0;
+}
+
+static int
+test_soc(void)
+{
+ if (test_compare_addr())
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(soc_autotest, test_soc);
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index dfd64aa..b414008 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_soc.h rte_pci.h
INC += 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_private.h b/lib/librte_eal/common/eal_private.h
index 431d6c2..df6582d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -36,6 +36,7 @@

#include <stdio.h>
#include <rte_pci.h>
+#include <rte_soc.h>

/**
* Initialize the memzone subsystem (private to eal).
@@ -126,6 +127,9 @@ int rte_eal_log_init(const char *id, int facility);
*/
int rte_eal_pci_init(void);

+struct rte_soc_driver;
+struct rte_soc_device;
+
struct rte_pci_driver;
struct rte_pci_device;

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..bc0a43b
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -0,0 +1,138 @@
+/*-
+ * 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 RehiveTech 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_
+
+/**
+ * @file
+ *
+ * RTE SoC Interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <rte_dev.h>
+#include <rte_debug.h>
+
+struct rte_soc_id {
+ const char *compatible; /**< OF compatible specification */
+ uint64_t priv_data; /**< SoC Driver specific data */
+};
+
+struct rte_soc_addr {
+ char *name; /**< name used in sysfs */
+ char *fdt_path; /**< path to the associated node in FDT */
+};
+
+/**
+ * A structure describing a SoC device.
+ */
+struct rte_soc_device {
+ TAILQ_ENTRY(rte_soc_device) next; /**< Next probed SoC device */
+ struct rte_device device; /**< Inherit code device */
+ struct rte_soc_addr addr; /**< SoC device Location */
+ struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_driver *driver; /**< Associated driver */
+};
+
+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 hotplugging.
+ */
+typedef int (soc_devuninit_t)(struct rte_soc_device *);
+
+/**
+ * A structure describing a SoC driver.
+ */
+struct rte_soc_driver {
+ TAILQ_ENTRY(rte_soc_driver) next; /**< Next in list */
+ struct rte_driver driver; /**< Inherit core driver. */
+ soc_devinit_t *devinit; /**< Device initialization */
+ soc_devuninit_t *devuninit; /**< Device uninitialization */
+ const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+};
+
+/**
+ * Utility function to write a SoC device name, this device name can later be
+ * used to retrieve the corresponding rte_soc_addr using above functions.
+ *
+ * @param addr
+ * The SoC address
+ * @param output
+ * The output buffer string
+ * @param size
+ * The output buffer size
+ * @return
+ * 0 on success, negative on error.
+ */
+static inline void
+rte_eal_soc_device_name(const struct rte_soc_addr *addr,
+ char *output, size_t size)
+{
+ int ret;
+
+ RTE_VERIFY(addr != NULL);
+ RTE_VERIFY(size >= strlen(addr->name));
+ ret = snprintf(output, size, "%s", addr->name);
+ RTE_VERIFY(ret >= 0);
+}
+
+static inline int
+rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
+ const struct rte_soc_addr *a1)
+{
+ if (a0 == NULL || a1 == NULL)
+ return -1;
+
+ RTE_VERIFY(a0->name != NULL);
+ RTE_VERIFY(a1->name != NULL);
+
+ return strcmp(a0->name, a1->name);
+}
+
+#endif
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:23 UTC
Permalink
Registeration of a SoC driver through a helper DRIVER_REGISTER_SOC
(on the lines of DRIVER_REGISTER_PCI). soc_driver_list stores all the
registered drivers.

Test case has been introduced to verify the registration and
deregistration.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/test_soc.c | 111 ++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 +
lib/librte_eal/common/eal_common_soc.c | 56 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 26 ++++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 +
6 files changed, 201 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index 916a863..ac03e64 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -75,6 +75,108 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd0"
+ },
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd1"
+ },
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->driver.name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd0 but '%s'",
+ drv->driver.name);
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}

@@ -84,6 +186,15 @@ test_soc(void)
if (test_compare_addr())
return -1;

+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 7b3d409..cda8009 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -168,4 +168,8 @@ DPDK_16.11 {

rte_eal_dev_attach;
rte_eal_dev_detach;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..56135ed
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+/* Global SoC driver list */
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index bc0a43b..16c5a1b 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -51,8 +51,14 @@ extern "C" {
#include <string.h>

#include <rte_dev.h>
+#include <rte_eal.h>
#include <rte_debug.h>

+extern struct soc_driver_list soc_driver_list;
+/**< Global list of SoC Drivers */
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
uint64_t priv_data; /**< SoC Driver specific data */
@@ -135,4 +141,24 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
return strcmp(a0->name, a1->name);
}

+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+/** Helper for SoC device registeration from PMD Drivers */
+#define DRIVER_REGISTER_SOC(nm, soc_drv) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{\
+ (soc_drv).driver.name = RTE_STR(nm);\
+ rte_eal_soc_register(&soc_drv); \
+} \
+DRIVER_EXPORT_NAME(nm, __COUNTER__)
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..a520477 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -77,6 +77,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b8bfd4b..66c1258 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -174,5 +174,8 @@ DPDK_16.11 {
rte_eal_dev_detach;
rte_eal_vdrv_register;
rte_eal_vdrv_unregister;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;

} DPDK_16.07;
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:24 UTC
Permalink
SoC devices would be linked in a separate list (from PCI). This is used for
probe function.
A helper for dumping the device list is added.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 2 ++
lib/librte_eal/common/eal_common_soc.c | 34 +++++++++++++++++++++++++
lib/librte_eal/common/include/rte_soc.h | 9 +++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 2 ++
4 files changed, 47 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index cda8009..de38848 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -169,7 +169,9 @@ DPDK_16.11 {
rte_eal_dev_attach;
rte_eal_dev_detach;
soc_driver_list;
+ soc_device_list
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_dump;

} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 56135ed..5dcddc5 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -31,6 +31,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

+#include <stddef.h>
+#include <stdio.h>
#include <sys/queue.h>

#include <rte_log.h>
@@ -40,6 +42,38 @@
/* Global SoC driver list */
struct soc_driver_list soc_driver_list =
TAILQ_HEAD_INITIALIZER(soc_driver_list);
+struct soc_device_list soc_device_list =
+ TAILQ_HEAD_INITIALIZER(soc_device_list);
+
+/* dump one device */
+static int
+soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
+{
+ int i;
+
+ fprintf(f, "%s", dev->addr.name);
+ fprintf(f, " - fdt_path: %s\n",
+ dev->addr.fdt_path ? dev->addr.fdt_path : "(none)");
+
+ for (i = 0; dev->id && dev->id[i].compatible; ++i)
+ fprintf(f, " %s\n", dev->id[i].compatible);
+
+ return 0;
+}
+
+/* dump devices on the bus to an output stream */
+void
+rte_eal_soc_dump(FILE *f)
+{
+ struct rte_soc_device *dev = NULL;
+
+ if (!f)
+ return;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ soc_dump_one_device(f, dev);
+ }
+}

/* register a driver */
void
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 16c5a1b..c6f98eb 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -56,8 +56,12 @@ extern "C" {

extern struct soc_driver_list soc_driver_list;
/**< Global list of SoC Drivers */
+extern struct soc_device_list soc_device_list;
+/**< Global list of SoC Devices */

TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */
+

struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -142,6 +146,11 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Dump discovered SoC devices.
+ */
+void rte_eal_soc_dump(FILE *f);
+
+/**
* Register a SoC driver.
*/
void rte_eal_soc_register(struct rte_soc_driver *driver);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 66c1258..b9d1932 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -175,7 +175,9 @@ DPDK_16.11 {
rte_eal_vdrv_register;
rte_eal_vdrv_unregister;
soc_driver_list;
+ soc_device_list;
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_dump;

} DPDK_16.07;
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:25 UTC
Permalink
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 1a1bab3..d97cf0a 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -855,6 +856,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;

+ case OPT_NO_SOC_NUM:
+ conf->no_soc = 1;
+ break;
+
case OPT_NO_HPET_NUM:
conf->no_hpet = 1;
break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 5f1367e..3a98e94 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -67,6 +67,7 @@ struct internal_config {
unsigned hugepage_unlink; /**< true to unlink backing files */
volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
volatile unsigned no_pci; /**< true to disable PCI */
+ volatile unsigned no_soc; /**< true to disable SoC */
volatile unsigned no_hpet; /**< true to disable HPET */
volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index a881c62..ba1e704 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -69,6 +69,8 @@ enum {
OPT_NO_HUGE_NUM,
#define OPT_NO_PCI "no-pci"
OPT_NO_PCI_NUM,
+#define OPT_NO_SOC "no-soc"
+ OPT_NO_SOC_NUM,
#define OPT_NO_SHCONF "no-shconf"
OPT_NO_SHCONF_NUM,
#define OPT_SOCKET_MEM "socket-mem"
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:26 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/eal.c | 4 +++
lib/librte_eal/bsdapp/eal/eal_soc.c | 46 ++++++++++++++++++++++++++++
lib/librte_eal/common/eal_private.h | 10 +++++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/eal.c | 3 ++
lib/librte_eal/linuxapp/eal/eal_soc.c | 56 +++++++++++++++++++++++++++++++++++
7 files changed, 121 insertions(+)
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 5a3fc1d..cf4bf78 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -57,6 +57,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_hugepage_info.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_thread.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_pci.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_lcore.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_timer.c
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a0c8f8c..7d8c3e8 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
#include <rte_string_fns.h>
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
+#include <rte_soc.h>
#include <rte_pci.h>
#include <rte_dev.h>
#include <rte_devargs.h>
@@ -567,6 +568,9 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
eal_check_mem_on_local_socket();

if (eal_plugins_init() < 0)
diff --git a/lib/librte_eal/bsdapp/eal/eal_soc.c b/lib/librte_eal/bsdapp/eal/eal_soc.c
new file mode 100644
index 0000000..cb297ff
--- /dev/null
+++ b/lib/librte_eal/bsdapp/eal/eal_soc.c
@@ -0,0 +1,46 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <rte_common.h>
+#include <rte_log.h>
+
+#include <eal_private.h>
+
+/* Init the SoC EAL subsystem */
+int
+rte_eal_soc_init(void)
+{
+ return 0;
+}
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index df6582d..ba8407d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -130,6 +130,16 @@ int rte_eal_pci_init(void);
struct rte_soc_driver;
struct rte_soc_device;

+/**
+ * Init the SoC infra.
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ * 0 on success, negative on error
+ */
+int rte_eal_soc_init(void);
+
struct rte_pci_driver;
struct rte_pci_device;

diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index a520477..59e30fa 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -65,6 +65,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_mp_sync.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_vfio.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 9412983..15c8c3d 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -798,6 +798,9 @@ rte_eal_init(int argc, char **argv)
rte_panic("Cannot init VFIO\n");
#endif

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
if (rte_eal_memory_init() < 0)
rte_panic("Cannot init memory\n");

diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
new file mode 100644
index 0000000..04848b9
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <rte_log.h>
+#include <rte_soc.h>
+
+#include "eal_internal_cfg.h"
+#include "eal_filesystem.h"
+#include "eal_private.h"
+
+/* Init the SoC EAL subsystem */
+int
+rte_eal_soc_init(void)
+{
+ return 0;
+}
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:28 UTC
Permalink
It is assumed that SoC Devices provided on command line are prefixed with
"soc:". This patch adds parse and attach support for such devices.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/eal_common_dev.c | 27 ++++++++++----
lib/librte_eal/common/eal_common_devargs.c | 17 +++++++++
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++++++++++++++++---
lib/librte_eal/common/include/rte_devargs.h | 8 +++++
lib/librte_eal/common/include/rte_soc.h | 24 +++++++++++++
5 files changed, 119 insertions(+), 12 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index d1f0ad8..fbc4443 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -106,17 +106,23 @@ rte_eal_dev_init(void)

int rte_eal_dev_attach(const char *name, const char *devargs)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;

if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_probe_one(&addr) < 0)
+ memset(&soc_addr, 0, sizeof(soc_addr));
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_probe_one(&soc_addr) < 0) {
+ free(soc_addr.name);
+ goto err;
+ }
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_probe_one(&pci_addr) < 0)
goto err;
-
} else {
if (rte_eal_vdev_init(name, devargs))
goto err;
@@ -131,15 +137,22 @@ err:

int rte_eal_dev_detach(const char *name)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;

if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_detach(&addr) < 0)
+ memset(&soc_addr, 0, sizeof(soc_addr));
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_detach(&soc_addr) < 0) {
+ free(soc_addr.name);
+ goto err;
+ }
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_detach(&pci_addr) < 0)
goto err;
} else {
if (rte_eal_vdev_uninit(name))
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index e403717..e1dae1a 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -41,6 +41,7 @@
#include <string.h>

#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_devargs.h>
#include "eal_private.h"

@@ -105,6 +106,14 @@ 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:
+ /* try to parse soc device with prefix "soc:" */
+ if (rte_eal_parse_soc_spec(buf, &devargs->soc.addr) != 0)
+ goto fail;
+ break;
+
case RTE_DEVTYPE_VIRTUAL:
/* save driver name */
ret = snprintf(devargs->virt.drv_name,
@@ -166,6 +175,14 @@ rte_eal_devargs_dump(FILE *f)
devargs->pci.addr.devid,
devargs->pci.addr.function,
devargs->args);
+ else if (devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ fprintf(f, " SoC whitelist %s %s\n",
+ devargs->soc.addr.name,
+ devargs->soc.addr.fdt_path);
+ else if (devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC)
+ fprintf(f, " SoC blacklist %s %s\n",
+ devargs->soc.addr.name,
+ devargs->soc.addr.fdt_path);
else if (devargs->type == RTE_DEVTYPE_VIRTUAL)
fprintf(f, " VIRTUAL %s %s\n",
devargs->virt.drv_name,
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 4797dd9..efa722d 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -37,6 +37,8 @@

#include <rte_log.h>
#include <rte_common.h>
+#include <rte_devargs.h>
+#include <rte_eal.h>
#include <rte_soc.h>

#include "eal_private.h"
@@ -47,6 +49,21 @@ struct soc_driver_list soc_driver_list =
struct soc_device_list soc_device_list =
TAILQ_HEAD_INITIALIZER(soc_device_list);

+static struct rte_devargs *soc_devargs_lookup(struct rte_soc_device *dev)
+{
+ struct rte_devargs *devargs;
+
+ TAILQ_FOREACH(devargs, &devargs_list, next) {
+ if (devargs->type != RTE_DEVTYPE_BLACKLISTED_SOC &&
+ devargs->type != RTE_DEVTYPE_WHITELISTED_SOC)
+ continue;
+ if (!rte_eal_compare_soc_addr(&dev->addr, &devargs->soc.addr))
+ return devargs;
+ }
+
+ return NULL;
+}
+
static int
rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
struct rte_soc_device *dev)
@@ -60,6 +77,18 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
return ret;
}

+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %d\n",
+ dev->addr.name, dev->device.numa_node);
+ RTE_LOG(DEBUG, EAL, " probe driver %s\n", drv->driver.name);
+
+ /* no initialization when blacklisted, return without error */
+ if (dev->device.devargs != NULL
+ && dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC) {
+ RTE_LOG(DEBUG, EAL,
+ " device is blacklisted, skipping\n");
+ return ret;
+ }
+
dev->driver = drv;
RTE_VERIFY(drv->devinit != NULL);
return drv->devinit(drv, dev);
@@ -104,8 +133,8 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
return ret;
}

- RTE_LOG(DEBUG, EAL, "SoC device %s\n",
- dev->addr.name);
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %i\n",
+ dev->addr.name, dev->device.numa_node);

RTE_LOG(DEBUG, EAL, " remove driver: %s\n", drv->driver.name);

@@ -218,13 +247,29 @@ int
rte_eal_soc_probe(void)
{
struct rte_soc_device *dev = NULL;
+ struct rte_devargs *devargs = NULL;
int ret = 0;
+ int probe_all = 0;
+
+ if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_SOC) == 0)
+ probe_all = 1;

TAILQ_FOREACH(dev, &soc_device_list, next) {
- ret = soc_probe_all_drivers(dev);
+
+ /* set devargs in SoC structure */
+ devargs = soc_devargs_lookup(dev);
+ if (devargs != NULL)
+ dev->device.devargs = devargs;
+
+ /* probe all or only whitelisted devices */
+ if (probe_all)
+ ret = soc_probe_all_drivers(dev);
+ else if (devargs != NULL &&
+ devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ ret = soc_probe_all_drivers(dev);
if (ret < 0)
- rte_exit(EXIT_FAILURE, "Requested device %s"
- " cannot be used\n", dev->addr.name);
+ rte_exit(EXIT_FAILURE, "Requested device %s "
+ "cannot be used\n", dev->addr.name);
}

return 0;
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 53c59f5..757320e 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,11 @@ struct rte_devargs {
/** PCI location. */
struct rte_pci_addr addr;
} pci;
+ /** Used if type is RTE_DEVTYPE_*_SOC. */
+ 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
index cc17829..c45b37e 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -158,6 +158,30 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Parse a specification of a soc device. The specification must differentiate
+ * a SoC device specification from the PCI bus and virtual devices. We assume
+ * a SoC specification starts with "soc:". The function allocates the name
+ * entry of the given addr.
+ *
+ * @return
+ * - 0 on success
+ * - 1 when not a SoC spec
+ * - -1 on failure
+ */
+static inline int
+rte_eal_parse_soc_spec(const char *spec, struct rte_soc_addr *addr)
+{
+ if (strstr(spec, "soc:") == spec) {
+ addr->name = strdup(spec + 4);
+ if (addr->name == NULL)
+ return -1;
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
* Probe SoC devices for registered drivers.
*/
int rte_eal_soc_probe(void);
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:27 UTC
Permalink
Each SoC PMD registers a set of callback for scanning its own bus/infra and
matching devices to drivers when probe is called.
This patch introduces the infra for calls to SoC scan on rte_eal_soc_init()
and match on rte_eal_soc_probe().

Patch also adds test case for scan and probe.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/test_soc.c | 138 ++++++++++++++++-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 3 +
lib/librte_eal/common/eal_common_soc.c | 191 ++++++++++++++++++++++++
lib/librte_eal/common/include/rte_soc.h | 37 +++++
lib/librte_eal/linuxapp/eal/eal.c | 5 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 16 ++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 +
7 files changed, 392 insertions(+), 1 deletion(-)

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index ac03e64..4eb8146 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -87,14 +87,45 @@ static int test_compare_addr(void)
*/
struct test_wrapper {
struct rte_soc_driver soc_drv;
+ struct rte_soc_device soc_dev;
};

+static int empty_pmd0_devinit(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+static int empty_pmd0_devuninit(struct rte_soc_device *dev);
+static void test_soc_scan_dev0_cb(void);
+static int test_soc_match_dev0_cb(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+static void test_soc_scan_dev1_cb(void);
+static int test_soc_match_dev1_cb(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+
+static int
+empty_pmd0_devinit(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+empty_pmd0_devuninit(struct rte_soc_device *dev)
+{
+ /* Release the memory associated with dev->addr.name */
+ free(dev->addr.name);
+
+ return 0;
+}
+
struct test_wrapper empty_pmd0 = {
.soc_drv = {
.driver = {
.name = "empty_pmd0"
},
- },
+ .devinit = empty_pmd0_devinit,
+ .devuninit = empty_pmd0_devuninit,
+ .scan_fn = test_soc_scan_dev0_cb,
+ .match_fn = test_soc_match_dev0_cb,
+ }
};

struct test_wrapper empty_pmd1 = {
@@ -102,9 +133,54 @@ struct test_wrapper empty_pmd1 = {
.driver = {
.name = "empty_pmd1"
},
+ .scan_fn = test_soc_scan_dev1_cb,
+ .match_fn = test_soc_match_dev1_cb,
},
};

+static void
+test_soc_scan_dev0_cb(void)
+{
+ /* SoC's scan would scan devices on its bus and add to
+ * soc_device_list
+ */
+ empty_pmd0.soc_dev.addr.name = strdup("empty_pmd0_dev");
+
+ TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd0.soc_dev, next);
+}
+
+static int
+test_soc_match_dev0_cb(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev)
+{
+ if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd0_dev"))
+ return 0;
+
+ return 1;
+}
+
+
+static void
+test_soc_scan_dev1_cb(void)
+{
+ /* SoC's scan would scan devices on its bus and add to
+ * soc_device_list
+ */
+ empty_pmd0.soc_dev.addr.name = strdup("empty_pmd1_dev");
+
+ TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd1.soc_dev, next);
+}
+
+static int
+test_soc_match_dev1_cb(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev)
+{
+ if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd1_dev"))
+ return 0;
+
+ return 1;
+}
+
static int
count_registered_socdrvs(void)
{
@@ -148,13 +224,54 @@ test_register_unregister(void)
return 0;
}

+/* Test Probe (scan and match) functionality */
+static int
+test_soc_init_and_probe(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* Registering dummy drivers */
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+ /* Assuming that test_register_unregister is working, not verifying
+ * that drivers are indeed registered
+ */
+
+ /* rte_eal_soc_init is called by rte_eal_init, which in turn calls the
+ * scan_fn of each driver.
+ */
+ TAILQ_FOREACH(drv, &soc_driver_list, next) {
+ if (drv && drv->scan_fn)
+ drv->scan_fn();
+ }
+
+ /* rte_eal_init() would perform other inits here */
+
+ /* Probe would link the SoC devices<=>drivers */
+ rte_eal_soc_probe();
+
+ /* Unregistering dummy drivers */
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ free(empty_pmd0.soc_dev.addr.name);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
/* save real devices and drivers until the tests finishes */
struct soc_driver_list real_soc_driver_list =
TAILQ_HEAD_INITIALIZER(real_soc_driver_list);

+/* save real devices and drivers until the tests finishes */
+struct soc_device_list real_soc_device_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_device_list);
+
static int test_soc_setup(void)
{
struct rte_soc_driver *drv;
+ struct rte_soc_device *dev;

/* no real drivers for the test */
while (!TAILQ_EMPTY(&soc_driver_list)) {
@@ -163,12 +280,20 @@ static int test_soc_setup(void)
TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
}

+ /* And, no real devices for the test */
+ while (!TAILQ_EMPTY(&soc_device_list)) {
+ dev = TAILQ_FIRST(&soc_device_list);
+ /* TODO: detach the device */
+ TAILQ_INSERT_TAIL(&real_soc_device_list, dev, next);
+ }
+
return 0;
}

static int test_soc_cleanup(void)
{
struct rte_soc_driver *drv;
+ struct rte_soc_device *dev;

/* bring back real drivers after the test */
while (!TAILQ_EMPTY(&real_soc_driver_list)) {
@@ -177,6 +302,13 @@ static int test_soc_cleanup(void)
rte_eal_soc_register(drv);
}

+ /* And, bring back real devices after the test */
+ while (!TAILQ_EMPTY(&real_soc_device_list)) {
+ dev = TAILQ_FIRST(&real_soc_device_list);
+ TAILQ_REMOVE(&real_soc_device_list, dev, next);
+ /* TODO: Attach the device */
+ }
+
return 0;
}

@@ -192,6 +324,10 @@ test_soc(void)
if (test_register_unregister())
return -1;

+ /* Assuming test_register_unregister has succeeded */
+ if (test_soc_init_and_probe())
+ return -1;
+
if (test_soc_cleanup())
return -1;

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index de38848..72b42d7 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -173,5 +173,8 @@ DPDK_16.11 {
rte_eal_soc_register;
rte_eal_soc_unregister;
rte_eal_soc_dump;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 5dcddc5..4797dd9 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -36,6 +36,8 @@
#include <sys/queue.h>

#include <rte_log.h>
+#include <rte_common.h>
+#include <rte_soc.h>

#include "eal_private.h"

@@ -45,6 +47,189 @@ struct soc_driver_list soc_driver_list =
struct soc_device_list soc_device_list =
TAILQ_HEAD_INITIALIZER(soc_device_list);

+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev)
+{
+ int ret = 1;
+
+ ret = drv->match_fn(drv, dev);
+ if (!ret) {
+ RTE_LOG(DEBUG, EAL,
+ " match function failed, skipping\n");
+ return ret;
+ }
+
+ dev->driver = drv;
+ RTE_VERIFY(drv->devinit != NULL);
+ return drv->devinit(drv, dev);
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_probe_one_driver(dr, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/* If the IDs match, call the devuninit() function of the driver. */
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev)
+{
+ int ret;
+
+ if ((drv == NULL) || (dev == NULL))
+ return -EINVAL;
+
+ ret = drv->match_fn(drv, dev);
+ if (!ret) {
+ RTE_LOG(DEBUG, EAL,
+ " match function failed, skipping\n");
+ return ret;
+ }
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+ dev->addr.name);
+
+ RTE_LOG(DEBUG, EAL, " remove driver: %s\n", drv->driver.name);
+
+ if (drv->devuninit && (drv->devuninit(dev) < 0))
+ return -1; /* negative value is an error */
+
+ /* clear driver structure */
+ dev->driver = NULL;
+
+ return 0;
+}
+
+/*
+ * Call the devuninit() function of all registered drivers for the given
+ * device if their IDs match.
+ *
+ * @return
+ * 0 when successful
+ * -1 if deinitialization fails
+ * 1 if no driver is found for this device.
+ */
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_detach_dev(dr, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Detach device specified by its SoC address.
+ */
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_detach_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+
+ TAILQ_REMOVE(&soc_device_list, dev, next);
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n",
+ dev->addr.name);
+ return -1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ /* unlike pci, in case of soc, it the responsibility of the soc driver
+ * to check during init whether device has been updated since last add.
+ */
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL,
+ "Requested device %s cannot be used\n", addr->name);
+ return -1;
+}
+
+/*
+ * Scan the SoC devices and call the devinit() function for all registered
+ * drivers that have a matching entry in its id_table for discovered devices.
+ */
+int
+rte_eal_soc_probe(void)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Requested device %s"
+ " cannot be used\n", dev->addr.name);
+ }
+
+ return 0;
+}
+
/* dump one device */
static int
soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
@@ -79,6 +264,12 @@ rte_eal_soc_dump(FILE *f)
void
rte_eal_soc_register(struct rte_soc_driver *driver)
{
+ /* For a valid soc driver, match and scan function
+ * should be provided.
+ */
+ RTE_VERIFY(driver != NULL);
+ RTE_VERIFY(driver->match_fn != NULL);
+ RTE_VERIFY(driver->scan_fn != NULL);
TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
}

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index c6f98eb..cc17829 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -97,6 +97,16 @@ typedef int (soc_devinit_t)(struct rte_soc_driver *, struct rte_soc_device *);
typedef int (soc_devuninit_t)(struct rte_soc_device *);

/**
+ * SoC device scan callback, called from rte_eal_soc_init.
+ */
+typedef void (soc_scan_t)(void);
+
+/**
+ * Custom device<=>driver match callback for SoC
+ */
+typedef int (soc_match_t)(struct rte_soc_driver *, struct rte_soc_device *);
+
+/**
* A structure describing a SoC driver.
*/
struct rte_soc_driver {
@@ -104,6 +114,8 @@ struct rte_soc_driver {
struct rte_driver driver; /**< Inherit core driver. */
soc_devinit_t *devinit; /**< Device initialization */
soc_devuninit_t *devuninit; /**< Device uninitialization */
+ soc_scan_t *scan_fn; /**< Callback for scanning SoC bus*/
+ soc_match_t *match_fn; /**< Callback to match dev<->drv */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
};

@@ -146,6 +158,31 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Probe SoC devices for registered drivers.
+ */
+int rte_eal_soc_probe(void);
+
+/**
+ * Probe the single SoC device.
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Scan the SoC devices and find the SoC device specified by the SoC
+ * address, then call the devuninit() function for registered driver
+ * that has a matching entry in its id_table for discovered device.
+ *
+ * @param addr
+ * The SoC address to close.
+ * @return
+ * - 0 on success.
+ * - Negative on error.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+/**
* Dump discovered SoC devices.
*/
void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 15c8c3d..147b601 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -70,6 +70,7 @@
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include <rte_common.h>
@@ -881,6 +882,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");

+ /* Probe & Initialize SoC devices */
+ if (rte_eal_soc_probe())
+ rte_panic("Cannot probe SoC\n");
+
rte_eal_mcfg_complete();

return fctret;
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 04848b9..5f961c4 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -52,5 +52,21 @@
int
rte_eal_soc_init(void)
{
+ struct rte_soc_driver *drv;
+
+ /* for debug purposes, SoC can be disabled */
+ if (internal_config.no_soc)
+ return 0;
+
+ /* For each registered driver, call their scan routine to perform any
+ * custom scan for devices (for example, custom buses)
+ */
+ TAILQ_FOREACH(drv, &soc_driver_list, next) {
+ if (drv && drv->scan_fn) {
+ drv->scan_fn();
+ /* Ignore all errors from this */
+ }
+ }
+
return 0;
}
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b9d1932..8092e62 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -179,5 +179,8 @@ DPDK_16.11 {
rte_eal_soc_register;
rte_eal_soc_unregister;
rte_eal_soc_dump;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.07;
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:29 UTC
Permalink
The flags are copied from the PCI ones. They should be refactorized into a
general set of flags in the future.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/include/rte_soc.h | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index c45b37e..d453398 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -117,8 +117,18 @@ struct rte_soc_driver {
soc_scan_t *scan_fn; /**< Callback for scanning SoC bus*/
soc_match_t *match_fn; /**< Callback to match dev<->drv */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+ uint32_t drv_flags; /**< Control handling of device */
};

+/** Device needs to map its resources by EAL */
+#define RTE_SOC_DRV_NEED_MAPPING 0x0001
+/** Device needs to be unbound even if no module is provieded */
+#define RTE_SOC_DRV_FORCE_UNBIND 0x0004
+/** Device driver supports link state interrupt */
+#define RTE_SOC_DRV_INTR_LSC 0x0008
+/** Device driver supports detaching capability */
+#define RTE_SOC_DRV_DETACHABLE 0x0010
+
/**
* Utility function to write a SoC device name, this device name can later be
* used to retrieve the corresponding rte_soc_addr using above functions.
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:30 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/include/rte_soc.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index d453398..bd496ed 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -53,6 +53,7 @@ extern "C" {
#include <rte_dev.h>
#include <rte_eal.h>
#include <rte_debug.h>
+#include <rte_interrupts.h>

extern struct soc_driver_list soc_driver_list;
/**< Global list of SoC Drivers */
@@ -81,6 +82,7 @@ struct rte_soc_device {
struct rte_device device; /**< Inherit code device */
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_intr_handle intr_handle; /**< Interrupt handle */
struct rte_soc_driver *driver; /**< Associated driver */
};
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:31 UTC
Permalink
It is not necessary to place the rte_pci_driver at the beginning
of the rte_eth_dev struct anymore as we use the container_of macro
to get the parent pointer.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 4 ++--
lib/librte_ether/rte_ethdev.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index d54ec9e..b10d985 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -242,7 +242,7 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,

int diag;

- eth_drv = (struct eth_driver *)pci_drv;
+ eth_drv = container_of(pci_drv, struct eth_driver, pci_drv);

rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
sizeof(ethdev_name));
@@ -303,7 +303,7 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
if (eth_dev == NULL)
return -ENODEV;

- eth_drv = (const struct eth_driver *)pci_dev->driver;
+ eth_drv = container_of(pci_dev->driver, struct eth_driver, pci_drv);

/* Invoke PMD device uninit function */
if (*eth_drv->eth_dev_uninit) {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 2a697ec..8320dc4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1842,7 +1842,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
* Each Ethernet driver acts as a PCI driver and is represented by a generic
* *eth_driver* structure that holds:
*
- * - An *rte_pci_driver* structure (which must be the first field).
+ * - An *rte_pci_driver* structure.
*
* - The *eth_dev_init* function invoked for each matching PCI device.
*
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:32 UTC
Permalink
Now that different types of ethdev exist, check for presence of PCI dev
while copying out the info.
Similar would be done for SoC.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index b10d985..e9f5467 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3200,6 +3200,8 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
return;
}

+ RTE_VERIFY(eth_dev->pci_dev != NULL);
+
eth_dev->data->dev_flags = 0;
if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:33 UTC
Permalink
We abstract access to the intr_handle here as we want to get
it either from the pci_dev or soc_dev.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e9f5467..104ea4a 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2526,6 +2526,17 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}

+static inline
+struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return &dev->pci_dev->intr_handle;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
{
@@ -2538,7 +2549,7 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);

dev = &rte_eth_devices[port_id];
- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
@@ -2598,7 +2609,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
return -EINVAL;
}

- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:34 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 104ea4a..4fa65ca 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2568,6 +2568,17 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
return 0;
}

+static inline
+const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return dev->driver->pci_drv.driver.name;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
const struct rte_memzone *
rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
uint16_t queue_id, size_t size, unsigned align,
@@ -2575,9 +2586,11 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
{
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
+ const char *drv_name;

+ drv_name = eth_dev_get_driver_name(dev);
snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
- dev->driver->pci_drv.driver.name, ring_name,
+ drv_name, ring_name,
dev->data->port_id, queue_id);

mz = rte_memzone_lookup(z_name);
--
2.7.4
Shreyansh Jain
2016-08-31 11:00:35 UTC
Permalink
- eth_driver/rte_eth_dev embeds rte_soc_driver/device for relating SoC
PMDs to ethernet devices.
- Add probe and remove functions linked to eth_dev_init/uninit

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 129 ++++++++++++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 31 ++++++++++
2 files changed, 160 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4fa65ca..b57d7b2 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -326,6 +326,101 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}

int
+rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+ int diag;
+
+ eth_drv = container_of(soc_drv, struct eth_driver, soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocate(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENOMEM;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev->data->dev_private = rte_zmalloc(
+ "ethdev private structure",
+ eth_drv->dev_private_size,
+ RTE_CACHE_LINE_SIZE);
+ if (eth_dev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private port "
+ "data\n");
+ }
+ eth_dev->soc_dev = soc_dev;
+ eth_dev->driver = eth_drv;
+ eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+ /*
+ * Set the default MTU.
+ */
+ eth_dev->data->mtu = ETHER_MTU;
+
+ /* Invoke PMD device initialization function */
+ diag = (*eth_drv->eth_dev_init)(eth_dev);
+ if (diag == 0)
+ return 0;
+
+ RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n",
+ soc_drv->driver.name,
+ soc_dev->addr.name);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+ rte_eth_dev_release_port(eth_dev);
+ return diag;
+}
+
+int
+rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocated(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENODEV;
+
+ eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv);
+
+ /* Invoke PMD device uninit function */
+ if (*eth_drv->eth_dev_uninit) {
+ ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+ if (ret)
+ return ret;
+ }
+
+ /* free ether device */
+ rte_eth_dev_release_port(eth_dev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ eth_dev->soc_dev = NULL;
+ eth_dev->driver = NULL;
+ eth_dev->data = NULL;
+
+ return 0;
+}
+
+
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1555,6 +1650,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
dev_info->driver_name = dev->data->drv_name;
dev_info->nb_rx_queues = dev->data->nb_rx_queues;
dev_info->nb_tx_queues = dev->data->nb_tx_queues;
@@ -2530,8 +2626,13 @@ static inline
struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return &dev->pci_dev->intr_handle;
}
+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return &dev->soc_dev->intr_handle;
+ }

RTE_VERIFY(0);
return NULL;
@@ -2572,9 +2673,15 @@ static inline
const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return dev->driver->pci_drv.driver.name;
}

+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return dev->driver->soc_drv.driver.name;
+ }
+
RTE_VERIFY(0);
return NULL;
}
@@ -3237,6 +3344,28 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
eth_dev->data->drv_name = pci_dev->driver->driver.name;
}

+void
+rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev)
+{
+ if ((eth_dev == NULL) || (soc_dev == NULL)) {
+ RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n",
+ eth_dev, soc_dev);
+ return;
+ }
+
+ RTE_VERIFY(eth_dev->soc_dev != NULL);
+
+ eth_dev->data->dev_flags = 0;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+ eth_dev->data->numa_node = soc_dev->device.numa_node;
+ eth_dev->data->drv_name = soc_dev->driver->driver.name;
+}
+
int
rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
struct rte_eth_l2_tunnel_conf *l2_tunnel)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 8320dc4..4ae22e9 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -180,6 +180,7 @@ extern "C" {
#include <rte_log.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include "rte_ether.h"
@@ -870,6 +871,7 @@ struct rte_eth_conf {
*/
struct rte_eth_dev_info {
struct rte_pci_device *pci_dev; /**< Device PCI information. */
+ struct rte_soc_device *soc_dev; /**< Device SoC information. */
const char *driver_name; /**< Device Driver name. */
unsigned int if_index; /**< Index to bound host interface, or 0 if none.
Use if_indextoname() to translate into an interface name. */
@@ -1619,6 +1621,7 @@ struct rte_eth_dev {
const struct eth_driver *driver;/**< Driver for this device */
const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */
/** User application callbacks for NIC interrupts */
struct rte_eth_dev_cb_list link_intr_cbs;
/**
@@ -1852,6 +1855,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
*/
struct eth_driver {
struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is also a SoC driver. */
eth_dev_init_t eth_dev_init; /**< Device init function. */
eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */
unsigned int dev_private_size; /**< Size of device private data. */
@@ -4244,6 +4248,20 @@ void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
struct rte_pci_device *pci_dev);

/**
+ * Copy SoC device info to the Ethernet device data.
+ *
+ * @param eth_dev
+ * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
+ * @param soc_dev
+ * The *soc_dev* pointer is the address of the *rte_soc_device* structure.
+ *
+ * @return
+ * - 0 on success, negative on error
+ */
+void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev);
+
+/**
* Create memzone for HW rings.
* malloc can't be used as the physical address is needed.
* If the memzone is already created, then this function returns a ptr
@@ -4356,6 +4374,19 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev);
+
#ifdef __cplusplus
}
#endif
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:44 UTC
Permalink
Introduction:
=============

This patch set is direct derivative of Jan's original series [1],[2].

- As this deviates substantially from original series, if need be I can
post it as a separate patch rather than v2. Please suggest.
- Also, there are comments on original v1 ([4]) which are _not_
incorporated in this series as they refer to section no more in new
version.
- This v3 version is based on the rte_driver/device patchset v9 [10].
That series introduced device structures (rte_driver/rte_device)
generalizing devices into PCI, VDEV, XXX. For the purpose of this
patchset, XXX=>SOC.

Aim:
====

As of now EAL is primarly focused on PCI initialization/probing.

rte_eal_init()
|- rte_eal_pci_init(): Find PCI devices from sysfs
|- ...
|- rte_eal_memzone_init()
|- ...
`- rte_eal_pci_probe(): Driver<=>Device initialization

This patchset introduces SoC framework which would enable SoC drivers and
drivers to be plugged into EAL, very similar to how PCI drivers/devices are
done today.

This is a stripped down version of PCI framework which allows the SoC PMDs
to implement their own routines for detecting devices and linking devices to
drivers.

1) Changes to EAL
rte_eal_init()
|- rte_eal_pci_init(): Find PCI devices from sysfs
|- rte_eal_soc_init(): Calls PMDs->scan_fn
|- ...
|- rte_eal_memzone_init()
|- ...
|- rte_eal_pci_probe(): Driver<=>Device initialization, PMD->devinit()
`- rte_eal_soc_probe(): Calls PMDs->match_fn and PMDs->devinit();

2) New device/driver structures:
- rte_soc_driver (inheriting rte_driver)
- rte_soc_device (inheriting rte_device)
- rte_eth_dev and eth_driver embedded rte_soc_device and rte_soc_driver,
respectively.

3) The SoC PMDs need to:
- define rte_soc_driver with necessary scan and match callbacks
- Register themselves using DRIVER_REGISTER_SOC()
- Implement respective bus scanning in the scan callbacks to add necessary
devices to SoC device list
- Implement necessary eth_dev_init/uninint for ethernet instances

4) Design considerations that are same as PCI:
- SoC initialization is being done through rte_eal_init(), just after PCI
initialization is done.
- As in case of PCI, probe is done after rte_eal_pci_probe() to link the
devices detected with the drivers registered.
- Device attach/detach functions are available and have been designed on
the lines of PCI framework.
- PMDs register using DRIVER_REGISTER_SOC, very similar to
DRIVER_REGISTER_PCI for PCI devices.
- Linked list of SoC driver and devices exists independent of the other
driver/device list, but inheriting rte_driver/rte_driver, these are also
part of a global list.

5) Design considerations that are different from PCI:
- Each driver implements its own scan and match function. PCI uses the BDF
format to read the device from sysfs, but this _may_not_ be a case for a
SoC ethernet device.
= This is an important change from initial proposal by Jan in [2]. Unlike
his attempt to use /sys/bus/platform, this patch relies on the PMD to
detect the devices. This is because SoC may require specific or
additional info for device detection. Further, SoC may have embedded
devices/MACs which require initialization which cannot be covered through
sysfs parsing.
= PCI based PMDs rely on EAL's capability to detect devices. This
proposal puts the onus on PMD to detect devices, add to soc_device_list
and wait for Probe. Matching, of device<=>driver is again PMD's callback.

Patchset Overview:
==================
- Patches 0001~0003 introduce the base infrastructure and test case
- Patch 0004 is for command line support for no-soc, on lines of no-pci
- Patch 0005 enables EAL to handle SoC type devices
- Patch 0006 adds support for scan and probe callbacks and updates the test
framework with relevant test case.
- Patch 0007~0009 enable device argument, driver specific flags and
interrupt handling related basic infra. Subsequent patches build up on
them.
- Patch 0010~0013 makes changes to PCI as well as ethdev code to remove
assumption that eth_driver is a PCI driver.
- Patch 0014 adds necessary ethdev probe/remove functions for PMDs to use
- Patch 0015 adds support for SoC driver/devices, along with probe/remove
functions for Cryptodev devices.

Future/Pending Changes:
=======================
- Device whitelisting/blacklist still relies on command line '-b' and '-c'
which are internally implemented using OPT_PCI_BLACKLIST/OPT_PCI_WHITELIST.
This needs to be changed to a generic form - OPT_DEV_*LIST - probably.
- No cryptodriver currently uses SoC framework - probably a example driver
can be created to demonstrate usage.

[1] http://dpdk.org/ml/archives/dev/2016-January/030915.html
[2] http://www.dpdk.org/ml/archives/dev/2016-May/038486.html
[3] http://dpdk.org/ml/archives/dev/2016-August/045707.html
[4] http://dpdk.org/ml/archives/dev/2016-May/038948.html
[5] http://dpdk.org/ml/archives/dev/2016-May/038953.html
[6] http://dpdk.org/ml/archives/dev/2016-May/038487.html
[7] http://dpdk.org/ml/archives/dev/2016-May/038488.html
[8] http://dpdk.org/ml/archives/dev/2016-May/038489.html
[9] http://dpdk.org/ml/archives/dev/2016-May/038491.html
[10] http://dpdk.org/ml/archives/dev/2016-September/046256.html

Changes since v2:
- Rebasing over rte_driver/device patchset v9 [10]
- Added cryptodev support for SoC
- Default match function for SoC device<=>Driver
- Some variables renamed to reflect 'drv' rather than 'dr'

Change since v1 [2]:
- Removed patch 1-5 which were for generalizing some PCI specific routines
into EAL. These patches are good-to-have but not directly linked to SoC
and hence would be proposed separately.
- Removed support for sysfs parsing (patches 6~9)
- Rebasing over the recent (v8) version of rte_driver/device patchset
- Rebasing over master (16.07)
- Changes to various map file to change API intro to 16.11 from 16.07

Shreyansh Jain (15):
eal/soc: introduce very essential SoC infra definitions
eal/soc: add rte_eal_soc_register/unregister logic
eal/soc: Implement SoC device list and dump
eal: introduce --no-soc option
eal/soc: init SoC infra from EAL
eal/soc: implement probing of drivers
eal/soc: extend and utilize devargs
eal/soc: add drv_flags
eal/soc: add intr_handle
ether: utilize container_of for pci_drv
ether: verify we copy info from a PCI device
ether: extract function eth_dev_get_intr_handle
ether: extract function eth_dev_get_driver_name
ether: Support rte_soc_driver/device for etherdev
eal/crypto: Support rte_soc_driver/device for cryptodev

app/test/Makefile | 1 +
app/test/test_soc.c | 337 +++++++++++++++++++++++
lib/librte_cryptodev/rte_cryptodev.c | 122 ++++++++-
lib/librte_cryptodev/rte_cryptodev.h | 3 +
lib/librte_cryptodev/rte_cryptodev_pmd.h | 18 +-
lib/librte_cryptodev/rte_cryptodev_version.map | 3 +
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/eal.c | 4 +
lib/librte_eal/bsdapp/eal/eal_soc.c | 46 ++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 10 +
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_common_dev.c | 27 +-
lib/librte_eal/common/eal_common_devargs.c | 17 ++
lib/librte_eal/common/eal_common_options.c | 5 +
lib/librte_eal/common/eal_common_soc.c | 350 ++++++++++++++++++++++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 +
lib/librte_eal/common/eal_private.h | 14 +
lib/librte_eal/common/include/rte_devargs.h | 8 +
lib/librte_eal/common/include/rte_soc.h | 260 ++++++++++++++++++
lib/librte_eal/linuxapp/eal/Makefile | 2 +
lib/librte_eal/linuxapp/eal/eal.c | 8 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 72 +++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 9 +
lib/librte_ether/rte_ethdev.c | 165 ++++++++++-
lib/librte_ether/rte_ethdev.h | 33 ++-
26 files changed, 1501 insertions(+), 19 deletions(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/common/eal_common_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:45 UTC
Permalink
Define initial structures and functions for the SoC infrastructure.
This patch supports only a very minimal functions for now.
More features will be added in the following commits.

Includes rte_device/rte_driver inheritance of
rte_soc_device/rte_soc_driver.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/Makefile | 1 +
app/test/test_soc.c | 90 +++++++++++++++++++++
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_private.h | 4 +
lib/librte_eal/common/include/rte_soc.h | 138 ++++++++++++++++++++++++++++++++
5 files changed, 234 insertions(+), 1 deletion(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h

diff --git a/app/test/Makefile b/app/test/Makefile
index 611d77a..64b261d 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -77,6 +77,7 @@ APP = test
#
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
SRCS-y += test.c
+SRCS-y += test_soc.c
SRCS-y += resource.c
SRCS-y += test_resource.c
test_resource.res: test_resource.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
new file mode 100644
index 0000000..916a863
--- /dev/null
+++ b/app/test/test_soc.c
@@ -0,0 +1,90 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_soc.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+static char *safe_strdup(const char *s)
+{
+ char *c = strdup(s);
+
+ if (c == NULL)
+ rte_panic("failed to strdup '%s'\n", s);
+
+ return c;
+}
+
+static int test_compare_addr(void)
+{
+ struct rte_soc_addr a0;
+ struct rte_soc_addr a1;
+ struct rte_soc_addr a2;
+
+ a0.name = safe_strdup("ethernet0");
+ a0.fdt_path = NULL;
+
+ a1.name = safe_strdup("ethernet0");
+ a1.fdt_path = NULL;
+
+ a2.name = safe_strdup("ethernet1");
+ a2.fdt_path = NULL;
+
+ TEST_ASSERT(!rte_eal_compare_soc_addr(&a0, &a1),
+ "Failed to compare two soc addresses that equal");
+ TEST_ASSERT(rte_eal_compare_soc_addr(&a0, &a2),
+ "Failed to compare two soc addresses that differs");
+
+ free(a2.name);
+ free(a1.name);
+ free(a0.name);
+ return 0;
+}
+
+static int
+test_soc(void)
+{
+ if (test_compare_addr())
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(soc_autotest, test_soc);
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index dfd64aa..b414008 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_soc.h rte_pci.h
INC += 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_private.h b/lib/librte_eal/common/eal_private.h
index 431d6c2..df6582d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -36,6 +36,7 @@

#include <stdio.h>
#include <rte_pci.h>
+#include <rte_soc.h>

/**
* Initialize the memzone subsystem (private to eal).
@@ -126,6 +127,9 @@ int rte_eal_log_init(const char *id, int facility);
*/
int rte_eal_pci_init(void);

+struct rte_soc_driver;
+struct rte_soc_device;
+
struct rte_pci_driver;
struct rte_pci_device;

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..bc0a43b
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -0,0 +1,138 @@
+/*-
+ * 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 RehiveTech 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_
+
+/**
+ * @file
+ *
+ * RTE SoC Interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <rte_dev.h>
+#include <rte_debug.h>
+
+struct rte_soc_id {
+ const char *compatible; /**< OF compatible specification */
+ uint64_t priv_data; /**< SoC Driver specific data */
+};
+
+struct rte_soc_addr {
+ char *name; /**< name used in sysfs */
+ char *fdt_path; /**< path to the associated node in FDT */
+};
+
+/**
+ * A structure describing a SoC device.
+ */
+struct rte_soc_device {
+ TAILQ_ENTRY(rte_soc_device) next; /**< Next probed SoC device */
+ struct rte_device device; /**< Inherit code device */
+ struct rte_soc_addr addr; /**< SoC device Location */
+ struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_driver *driver; /**< Associated driver */
+};
+
+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 hotplugging.
+ */
+typedef int (soc_devuninit_t)(struct rte_soc_device *);
+
+/**
+ * A structure describing a SoC driver.
+ */
+struct rte_soc_driver {
+ TAILQ_ENTRY(rte_soc_driver) next; /**< Next in list */
+ struct rte_driver driver; /**< Inherit core driver. */
+ soc_devinit_t *devinit; /**< Device initialization */
+ soc_devuninit_t *devuninit; /**< Device uninitialization */
+ const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+};
+
+/**
+ * Utility function to write a SoC device name, this device name can later be
+ * used to retrieve the corresponding rte_soc_addr using above functions.
+ *
+ * @param addr
+ * The SoC address
+ * @param output
+ * The output buffer string
+ * @param size
+ * The output buffer size
+ * @return
+ * 0 on success, negative on error.
+ */
+static inline void
+rte_eal_soc_device_name(const struct rte_soc_addr *addr,
+ char *output, size_t size)
+{
+ int ret;
+
+ RTE_VERIFY(addr != NULL);
+ RTE_VERIFY(size >= strlen(addr->name));
+ ret = snprintf(output, size, "%s", addr->name);
+ RTE_VERIFY(ret >= 0);
+}
+
+static inline int
+rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
+ const struct rte_soc_addr *a1)
+{
+ if (a0 == NULL || a1 == NULL)
+ return -1;
+
+ RTE_VERIFY(a0->name != NULL);
+ RTE_VERIFY(a1->name != NULL);
+
+ return strcmp(a0->name, a1->name);
+}
+
+#endif
--
2.7.4
Hunt, David
2016-09-15 12:58:47 UTC
Permalink
Post by Jan Viktorin
Define initial structures and functions for the SoC infrastructure.
This patch supports only a very minimal functions for now.
More features will be added in the following commits.
Includes rte_device/rte_driver inheritance of
rte_soc_device/rte_soc_driver.
---
app/test/Makefile | 1 +
app/test/test_soc.c | 90 +++++++++++++++++++++
lib/librte_eal/common/Makefile | 2 +-
lib/librte_eal/common/eal_private.h | 4 +
lib/librte_eal/common/include/rte_soc.h | 138 ++++++++++++++++++++++++++++++++
5 files changed, 234 insertions(+), 1 deletion(-)
create mode 100644 app/test/test_soc.c
create mode 100644 lib/librte_eal/common/include/rte_soc.h
diff --git a/app/test/Makefile b/app/test/Makefile
index 611d77a..64b261d 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -77,6 +77,7 @@ APP = test
#
SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
SRCS-y += test.c
+SRCS-y += test_soc.c
SRCS-y += resource.c
SRCS-y += test_resource.c
test_resource.res: test_resource.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
new file mode 100644
index 0000000..916a863
--- /dev/null
+++ b/app/test/test_soc.c
@@ -0,0 +1,90 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ * All rights reserved.
Remove un-needed "All rights reserved"
Post by Jan Viktorin
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ *
+ * * 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 RehiveTech 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_soc.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+static char *safe_strdup(const char *s)
+{
+ char *c = strdup(s);
+
+ if (c == NULL)
+ rte_panic("failed to strdup '%s'\n", s);
+
+ return c;
+}
+
+static int test_compare_addr(void)
+{
+ struct rte_soc_addr a0;
+ struct rte_soc_addr a1;
+ struct rte_soc_addr a2;
+
+ a0.name = safe_strdup("ethernet0");
+ a0.fdt_path = NULL;
+
+ a1.name = safe_strdup("ethernet0");
+ a1.fdt_path = NULL;
+
+ a2.name = safe_strdup("ethernet1");
+ a2.fdt_path = NULL;
+
+ TEST_ASSERT(!rte_eal_compare_soc_addr(&a0, &a1),
+ "Failed to compare two soc addresses that equal");
+ TEST_ASSERT(rte_eal_compare_soc_addr(&a0, &a2),
+ "Failed to compare two soc addresses that differs");
+
+ free(a2.name);
+ free(a1.name);
+ free(a0.name);
+ return 0;
+}
+
+static int
+test_soc(void)
+{
+ if (test_compare_addr())
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(soc_autotest, test_soc);
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index dfd64aa..b414008 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_soc.h rte_pci.h
INC += 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_private.h b/lib/librte_eal/common/eal_private.h
index 431d6c2..df6582d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <rte_pci.h>
+#include <rte_soc.h>
/**
* Initialize the memzone subsystem (private to eal).
@@ -126,6 +127,9 @@ int rte_eal_log_init(const char *id, int facility);
*/
int rte_eal_pci_init(void);
+struct rte_soc_driver;
+struct rte_soc_device;
+
struct rte_pci_driver;
struct rte_pci_device;
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..bc0a43b
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -0,0 +1,138 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ * All rights reserved.
Remove un-needed "All rights reserved"
Post by Jan Viktorin
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ *
+ * * 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 RehiveTech 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_
+
+/**
+ *
+ * RTE SoC Interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <rte_dev.h>
+#include <rte_debug.h>
+
+struct rte_soc_id {
+ const char *compatible; /**< OF compatible specification */
+ uint64_t priv_data; /**< SoC Driver specific data */
+};
+
+struct rte_soc_addr {
+ char *name; /**< name used in sysfs */
+ char *fdt_path; /**< path to the associated node in FDT */
+};
+
+/**
+ * A structure describing a SoC device.
+ */
+struct rte_soc_device {
+ TAILQ_ENTRY(rte_soc_device) next; /**< Next probed SoC device */
+ struct rte_device device; /**< Inherit code device */
+ struct rte_soc_addr addr; /**< SoC device Location */
+ struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_soc_driver *driver; /**< Associated driver */
+};
+
+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 hotplugging.
+ */
+typedef int (soc_devuninit_t)(struct rte_soc_device *);
+
+/**
+ * A structure describing a SoC driver.
+ */
+struct rte_soc_driver {
+ TAILQ_ENTRY(rte_soc_driver) next; /**< Next in list */
+ struct rte_driver driver; /**< Inherit core driver. */
+ soc_devinit_t *devinit; /**< Device initialization */
+ soc_devuninit_t *devuninit; /**< Device uninitialization */
+ const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+};
+
+/**
+ * Utility function to write a SoC device name, this device name can later be
+ * used to retrieve the corresponding rte_soc_addr using above functions.
+ *
+ * The SoC address
+ * The output buffer string
+ * The output buffer size
+ * 0 on success, negative on error.
+ */
+static inline void
+rte_eal_soc_device_name(const struct rte_soc_addr *addr,
+ char *output, size_t size)
+{
+ int ret;
+
+ RTE_VERIFY(addr != NULL);
+ RTE_VERIFY(size >= strlen(addr->name));
+ ret = snprintf(output, size, "%s", addr->name);
+ RTE_VERIFY(ret >= 0);
+}
+
+static inline int
+rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
+ const struct rte_soc_addr *a1)
+{
+ if (a0 == NULL || a1 == NULL)
+ return -1;
+
+ RTE_VERIFY(a0->name != NULL);
+ RTE_VERIFY(a1->name != NULL);
+
+ return strcmp(a0->name, a1->name);
+}
+
+#endif
Shreyansh Jain
2016-09-09 08:43:46 UTC
Permalink
Registeration of a SoC driver through a helper DRIVER_REGISTER_SOC
(on the lines of DRIVER_REGISTER_PCI). soc_driver_list stores all the
registered drivers.

Test case has been introduced to verify the registration and
deregistration.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/test_soc.c | 111 ++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 +
lib/librte_eal/common/eal_common_soc.c | 56 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 26 ++++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 +
6 files changed, 201 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index 916a863..ac03e64 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -75,6 +75,108 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd0"
+ },
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd1"
+ },
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->driver.name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd0 but '%s'",
+ drv->driver.name);
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}

@@ -84,6 +186,15 @@ test_soc(void)
if (test_compare_addr())
return -1;

+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 7b3d409..cda8009 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -168,4 +168,8 @@ DPDK_16.11 {

rte_eal_dev_attach;
rte_eal_dev_detach;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..56135ed
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+/* Global SoC driver list */
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index bc0a43b..16c5a1b 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -51,8 +51,14 @@ extern "C" {
#include <string.h>

#include <rte_dev.h>
+#include <rte_eal.h>
#include <rte_debug.h>

+extern struct soc_driver_list soc_driver_list;
+/**< Global list of SoC Drivers */
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
uint64_t priv_data; /**< SoC Driver specific data */
@@ -135,4 +141,24 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
return strcmp(a0->name, a1->name);
}

+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+/** Helper for SoC device registeration from PMD Drivers */
+#define DRIVER_REGISTER_SOC(nm, soc_drv) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{\
+ (soc_drv).driver.name = RTE_STR(nm);\
+ rte_eal_soc_register(&soc_drv); \
+} \
+DRIVER_EXPORT_NAME(nm, __COUNTER__)
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..a520477 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -77,6 +77,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b8bfd4b..66c1258 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -174,5 +174,8 @@ DPDK_16.11 {
rte_eal_dev_detach;
rte_eal_vdrv_register;
rte_eal_vdrv_unregister;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;

} DPDK_16.07;
--
2.7.4
Hunt, David
2016-09-15 13:00:25 UTC
Permalink
Post by Shreyansh Jain
Registeration of a SoC driver through a helper DRIVER_REGISTER_SOC
(on the lines of DRIVER_REGISTER_PCI). soc_driver_list stores all the
registered drivers.
Test case has been introduced to verify the registration and
deregistration.
---
app/test/test_soc.c | 111 ++++++++++++++++++++++++
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 +
lib/librte_eal/common/eal_common_soc.c | 56 ++++++++++++
lib/librte_eal/common/include/rte_soc.h | 26 ++++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 +
6 files changed, 201 insertions(+)
create mode 100644 lib/librte_eal/common/eal_common_soc.c
diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index 916a863..ac03e64 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -75,6 +75,108 @@ static int test_compare_addr(void)
free(a2.name);
free(a1.name);
free(a0.name);
+
+ return 0;
+}
+
+/**
+ * Empty PMD driver based on the SoC infra.
+ *
+ * The rte_soc_device is usually wrapped in some higher-level struct
+ * (eth_driver). We simulate such a wrapper with an anonymous struct here.
+ */
+struct test_wrapper {
+ struct rte_soc_driver soc_drv;
+};
+
+struct test_wrapper empty_pmd0 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd0"
+ },
+ },
+};
+
+struct test_wrapper empty_pmd1 = {
+ .soc_drv = {
+ .driver = {
+ .name = "empty_pmd1"
+ },
+ },
+};
+
+static int
+count_registered_socdrvs(void)
+{
+ int i;
+ struct rte_soc_driver *drv;
+
+ i = 0;
+ TAILQ_FOREACH(drv, &soc_driver_list, next)
+ i += 1;
+
+ return i;
+}
+
+static int
+test_register_unregister(void)
+{
+ struct rte_soc_driver *drv;
+ int count;
+
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+
+ TEST_ASSERT(!TAILQ_EMPTY(&soc_driver_list),
+ "No PMD is present but the empty_pmd0 should be there");
+ drv = TAILQ_FIRST(&soc_driver_list);
+ TEST_ASSERT(!strcmp(drv->driver.name, "empty_pmd0"),
+ "The registered PMD is not empty_pmd0 but '%s'",
+ drv->driver.name);
+
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 2, "Expected 2 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ count = count_registered_socdrvs();
+ TEST_ASSERT_EQUAL(count, 1, "Expected 1 PMDs but detected %d", count);
+
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
+/* save real devices and drivers until the tests finishes */
+struct soc_driver_list real_soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_driver_list);
+
+static int test_soc_setup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* no real drivers for the test */
+ while (!TAILQ_EMPTY(&soc_driver_list)) {
+ drv = TAILQ_FIRST(&soc_driver_list);
+ rte_eal_soc_unregister(drv);
+ TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
+ }
+
+ return 0;
+}
+
+static int test_soc_cleanup(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* bring back real drivers after the test */
+ while (!TAILQ_EMPTY(&real_soc_driver_list)) {
+ drv = TAILQ_FIRST(&real_soc_driver_list);
+ TAILQ_REMOVE(&real_soc_driver_list, drv, next);
+ rte_eal_soc_register(drv);
+ }
+
return 0;
}
@@ -84,6 +186,15 @@ test_soc(void)
if (test_compare_addr())
return -1;
+ if (test_soc_setup())
+ return -1;
+
+ if (test_register_unregister())
+ return -1;
+
+ if (test_soc_cleanup())
+ return -1;
+
return 0;
}
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 7b3d409..cda8009 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -168,4 +168,8 @@ DPDK_16.11 {
rte_eal_dev_attach;
rte_eal_dev_detach;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
+
} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
new file mode 100644
index 0000000..56135ed
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -0,0 +1,56 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ * All rights reserved.
Duplicate "All rights reserved"
Post by Shreyansh Jain
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ *
+ * * 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 RehiveTech 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.
+ */
+
+#include <sys/queue.h>
+
+#include <rte_log.h>
+
+#include "eal_private.h"
+
+/* Global SoC driver list */
+struct soc_driver_list soc_driver_list =
+ TAILQ_HEAD_INITIALIZER(soc_driver_list);
+
+/* register a driver */
+void
+rte_eal_soc_register(struct rte_soc_driver *driver)
+{
+ TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
+}
+
+/* unregister a driver */
+void
+rte_eal_soc_unregister(struct rte_soc_driver *driver)
+{
+ TAILQ_REMOVE(&soc_driver_list, driver, next);
+}
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index bc0a43b..16c5a1b 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -51,8 +51,14 @@ extern "C" {
#include <string.h>
#include <rte_dev.h>
+#include <rte_eal.h>
#include <rte_debug.h>
+extern struct soc_driver_list soc_driver_list;
+/**< Global list of SoC Drivers */
+
+TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+
struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
uint64_t priv_data; /**< SoC Driver specific data */
@@ -135,4 +141,24 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
return strcmp(a0->name, a1->name);
}
+/**
+ * Register a SoC driver.
+ */
+void rte_eal_soc_register(struct rte_soc_driver *driver);
+
+/** Helper for SoC device registeration from PMD Drivers */
+#define DRIVER_REGISTER_SOC(nm, soc_drv) \
+RTE_INIT(socinitfn_ ##name); \
+static void socinitfn_ ##name(void) \
+{\
+ (soc_drv).driver.name = RTE_STR(nm);\
+ rte_eal_soc_register(&soc_drv); \
+} \
+DRIVER_EXPORT_NAME(nm, __COUNTER__)
+
+/**
+ * Unregister a SoC driver.
+ */
+void rte_eal_soc_unregister(struct rte_soc_driver *driver);
+
#endif
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..a520477 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -77,6 +77,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b8bfd4b..66c1258 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -174,5 +174,8 @@ DPDK_16.11 {
rte_eal_dev_detach;
rte_eal_vdrv_register;
rte_eal_vdrv_unregister;
+ soc_driver_list;
+ rte_eal_soc_register;
+ rte_eal_soc_unregister;
I believe people prefer these entries to be in alphabetical order.
Post by Shreyansh Jain
} DPDK_16.07;
Shreyansh Jain
2016-09-09 08:43:47 UTC
Permalink
SoC devices would be linked in a separate list (from PCI). This is used for
probe function.
A helper for dumping the device list is added.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 2 ++
lib/librte_eal/common/eal_common_soc.c | 34 +++++++++++++++++++++++++
lib/librte_eal/common/include/rte_soc.h | 9 +++++++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 2 ++
4 files changed, 47 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index cda8009..de38848 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -169,7 +169,9 @@ DPDK_16.11 {
rte_eal_dev_attach;
rte_eal_dev_detach;
soc_driver_list;
+ soc_device_list
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_dump;

} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 56135ed..5dcddc5 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -31,6 +31,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

+#include <stddef.h>
+#include <stdio.h>
#include <sys/queue.h>

#include <rte_log.h>
@@ -40,6 +42,38 @@
/* Global SoC driver list */
struct soc_driver_list soc_driver_list =
TAILQ_HEAD_INITIALIZER(soc_driver_list);
+struct soc_device_list soc_device_list =
+ TAILQ_HEAD_INITIALIZER(soc_device_list);
+
+/* dump one device */
+static int
+soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
+{
+ int i;
+
+ fprintf(f, "%s", dev->addr.name);
+ fprintf(f, " - fdt_path: %s\n",
+ dev->addr.fdt_path ? dev->addr.fdt_path : "(none)");
+
+ for (i = 0; dev->id && dev->id[i].compatible; ++i)
+ fprintf(f, " %s\n", dev->id[i].compatible);
+
+ return 0;
+}
+
+/* dump devices on the bus to an output stream */
+void
+rte_eal_soc_dump(FILE *f)
+{
+ struct rte_soc_device *dev = NULL;
+
+ if (!f)
+ return;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ soc_dump_one_device(f, dev);
+ }
+}

/* register a driver */
void
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 16c5a1b..c6f98eb 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -56,8 +56,12 @@ extern "C" {

extern struct soc_driver_list soc_driver_list;
/**< Global list of SoC Drivers */
+extern struct soc_device_list soc_device_list;
+/**< Global list of SoC Devices */

TAILQ_HEAD(soc_driver_list, rte_soc_driver); /**< SoC drivers in D-linked Q. */
+TAILQ_HEAD(soc_device_list, rte_soc_device); /**< SoC devices in D-linked Q. */
+

struct rte_soc_id {
const char *compatible; /**< OF compatible specification */
@@ -142,6 +146,11 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Dump discovered SoC devices.
+ */
+void rte_eal_soc_dump(FILE *f);
+
+/**
* Register a SoC driver.
*/
void rte_eal_soc_register(struct rte_soc_driver *driver);
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 66c1258..b9d1932 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -175,7 +175,9 @@ DPDK_16.11 {
rte_eal_vdrv_register;
rte_eal_vdrv_unregister;
soc_driver_list;
+ soc_device_list;
rte_eal_soc_register;
rte_eal_soc_unregister;
+ rte_eal_soc_dump;

} DPDK_16.07;
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:48 UTC
Permalink
This option has the same meaning for the SoC infra as the --no-pci
for the PCI infra.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/eal_common_options.c | 5 +++++
lib/librte_eal/common/eal_internal_cfg.h | 1 +
lib/librte_eal/common/eal_options.h | 2 ++
3 files changed, 8 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 1a1bab3..d97cf0a 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -85,6 +85,7 @@ eal_long_options[] = {
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
+ {OPT_NO_SOC, 0, NULL, OPT_NO_SOC_NUM },
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
@@ -855,6 +856,10 @@ eal_parse_common_option(int opt, const char *optarg,
conf->no_pci = 1;
break;

+ case OPT_NO_SOC_NUM:
+ conf->no_soc = 1;
+ break;
+
case OPT_NO_HPET_NUM:
conf->no_hpet = 1;
break;
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index 5f1367e..3a98e94 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -67,6 +67,7 @@ struct internal_config {
unsigned hugepage_unlink; /**< true to unlink backing files */
volatile unsigned xen_dom0_support; /**< support app running on Xen Dom0*/
volatile unsigned no_pci; /**< true to disable PCI */
+ volatile unsigned no_soc; /**< true to disable SoC */
volatile unsigned no_hpet; /**< true to disable HPET */
volatile unsigned vmware_tsc_map; /**< true to use VMware TSC mapping
* instead of native TSC */
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index a881c62..ba1e704 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -69,6 +69,8 @@ enum {
OPT_NO_HUGE_NUM,
#define OPT_NO_PCI "no-pci"
OPT_NO_PCI_NUM,
+#define OPT_NO_SOC "no-soc"
+ OPT_NO_SOC_NUM,
#define OPT_NO_SHCONF "no-shconf"
OPT_NO_SHCONF_NUM,
#define OPT_SOCKET_MEM "socket-mem"
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:49 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/bsdapp/eal/Makefile | 1 +
lib/librte_eal/bsdapp/eal/eal.c | 4 +++
lib/librte_eal/bsdapp/eal/eal_soc.c | 46 ++++++++++++++++++++++++++++
lib/librte_eal/common/eal_private.h | 10 +++++++
lib/librte_eal/linuxapp/eal/Makefile | 1 +
lib/librte_eal/linuxapp/eal/eal.c | 3 ++
lib/librte_eal/linuxapp/eal/eal_soc.c | 56 +++++++++++++++++++++++++++++++++++
7 files changed, 121 insertions(+)
create mode 100644 lib/librte_eal/bsdapp/eal/eal_soc.c
create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c

diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
index 5a3fc1d..cf4bf78 100644
--- a/lib/librte_eal/bsdapp/eal/Makefile
+++ b/lib/librte_eal/bsdapp/eal/Makefile
@@ -57,6 +57,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_hugepage_info.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_thread.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_pci.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_lcore.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_timer.c
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index a0c8f8c..7d8c3e8 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
#include <rte_string_fns.h>
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
+#include <rte_soc.h>
#include <rte_pci.h>
#include <rte_dev.h>
#include <rte_devargs.h>
@@ -567,6 +568,9 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
eal_check_mem_on_local_socket();

if (eal_plugins_init() < 0)
diff --git a/lib/librte_eal/bsdapp/eal/eal_soc.c b/lib/librte_eal/bsdapp/eal/eal_soc.c
new file mode 100644
index 0000000..cb297ff
--- /dev/null
+++ b/lib/librte_eal/bsdapp/eal/eal_soc.c
@@ -0,0 +1,46 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <rte_common.h>
+#include <rte_log.h>
+
+#include <eal_private.h>
+
+/* Init the SoC EAL subsystem */
+int
+rte_eal_soc_init(void)
+{
+ return 0;
+}
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index df6582d..ba8407d 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -130,6 +130,16 @@ int rte_eal_pci_init(void);
struct rte_soc_driver;
struct rte_soc_device;

+/**
+ * Init the SoC infra.
+ *
+ * This function is private to EAL.
+ *
+ * @return
+ * 0 on success, negative on error
+ */
+int rte_eal_soc_init(void);
+
struct rte_pci_driver;
struct rte_pci_device;

diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index a520477..59e30fa 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -65,6 +65,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_mp_sync.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_uio.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_vfio.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_soc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_debug.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 9412983..15c8c3d 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -798,6 +798,9 @@ rte_eal_init(int argc, char **argv)
rte_panic("Cannot init VFIO\n");
#endif

+ if (rte_eal_soc_init() < 0)
+ rte_panic("Cannot init SoC\n");
+
if (rte_eal_memory_init() < 0)
rte_panic("Cannot init memory\n");

diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
new file mode 100644
index 0000000..04848b9
--- /dev/null
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -0,0 +1,56 @@
+/*-
+ * 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 RehiveTech 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <rte_log.h>
+#include <rte_soc.h>
+
+#include "eal_internal_cfg.h"
+#include "eal_filesystem.h"
+#include "eal_private.h"
+
+/* Init the SoC EAL subsystem */
+int
+rte_eal_soc_init(void)
+{
+ return 0;
+}
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:50 UTC
Permalink
Each SoC PMD registers a set of callback for scanning its own bus/infra and
matching devices to drivers when probe is called.
This patch introduces the infra for calls to SoC scan on rte_eal_soc_init()
and match on rte_eal_soc_probe().

Patch also adds test case for scan and probe.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
app/test/test_soc.c | 138 ++++++++++++++-
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 +
lib/librte_eal/common/eal_common_soc.c | 215 ++++++++++++++++++++++++
lib/librte_eal/common/include/rte_soc.h | 51 ++++++
lib/librte_eal/linuxapp/eal/eal.c | 5 +
lib/librte_eal/linuxapp/eal/eal_soc.c | 16 ++
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
7 files changed, 432 insertions(+), 1 deletion(-)

diff --git a/app/test/test_soc.c b/app/test/test_soc.c
index ac03e64..d2b9462 100644
--- a/app/test/test_soc.c
+++ b/app/test/test_soc.c
@@ -87,14 +87,45 @@ static int test_compare_addr(void)
*/
struct test_wrapper {
struct rte_soc_driver soc_drv;
+ struct rte_soc_device soc_dev;
};

+static int empty_pmd0_devinit(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+static int empty_pmd0_devuninit(struct rte_soc_device *dev);
+static void test_soc_scan_dev0_cb(void);
+static int test_soc_match_dev0_cb(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+static void test_soc_scan_dev1_cb(void);
+static int test_soc_match_dev1_cb(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev);
+
+static int
+empty_pmd0_devinit(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+empty_pmd0_devuninit(struct rte_soc_device *dev)
+{
+ /* Release the memory associated with dev->addr.name */
+ free(dev->addr.name);
+
+ return 0;
+}
+
struct test_wrapper empty_pmd0 = {
.soc_drv = {
.driver = {
.name = "empty_pmd0"
},
- },
+ .devinit = empty_pmd0_devinit,
+ .devuninit = empty_pmd0_devuninit,
+ .scan_fn = test_soc_scan_dev0_cb,
+ .match_fn = test_soc_match_dev0_cb,
+ }
};

struct test_wrapper empty_pmd1 = {
@@ -102,9 +133,54 @@ struct test_wrapper empty_pmd1 = {
.driver = {
.name = "empty_pmd1"
},
+ .scan_fn = test_soc_scan_dev1_cb,
+ .match_fn = test_soc_match_dev1_cb,
},
};

+static void
+test_soc_scan_dev0_cb(void)
+{
+ /* SoC's scan would scan devices on its bus and add to
+ * soc_device_list
+ */
+ empty_pmd0.soc_dev.addr.name = strdup("empty_pmd0_dev");
+
+ TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd0.soc_dev, next);
+}
+
+static int
+test_soc_match_dev0_cb(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev)
+{
+ if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd0_dev"))
+ return 0;
+
+ return 1;
+}
+
+
+static void
+test_soc_scan_dev1_cb(void)
+{
+ /* SoC's scan would scan devices on its bus and add to
+ * soc_device_list
+ */
+ empty_pmd0.soc_dev.addr.name = strdup("empty_pmd1_dev");
+
+ TAILQ_INSERT_TAIL(&soc_device_list, &empty_pmd1.soc_dev, next);
+}
+
+static int
+test_soc_match_dev1_cb(struct rte_soc_driver *drv __rte_unused,
+ struct rte_soc_device *dev)
+{
+ if (!dev->addr.name || strcmp(dev->addr.name, "empty_pmd1_dev"))
+ return 0;
+
+ return 1;
+}
+
static int
count_registered_socdrvs(void)
{
@@ -148,13 +224,54 @@ test_register_unregister(void)
return 0;
}

+/* Test Probe (scan and match) functionality */
+static int
+test_soc_init_and_probe(void)
+{
+ struct rte_soc_driver *drv;
+
+ /* Registering dummy drivers */
+ rte_eal_soc_register(&empty_pmd0.soc_drv);
+ rte_eal_soc_register(&empty_pmd1.soc_drv);
+ /* Assuming that test_register_unregister is working, not verifying
+ * that drivers are indeed registered
+ */
+
+ /* rte_eal_soc_init is called by rte_eal_init, which in turn calls the
+ * scan_fn of each driver.
+ */
+ TAILQ_FOREACH(drv, &soc_driver_list, next) {
+ if (drv && drv->scan_fn)
+ drv->scan_fn();
+ }
+
+ /* rte_eal_init() would perform other inits here */
+
+ /* Probe would link the SoC devices<=>drivers */
+ rte_eal_soc_probe();
+
+ /* Unregistering dummy drivers */
+ rte_eal_soc_unregister(&empty_pmd0.soc_drv);
+ rte_eal_soc_unregister(&empty_pmd1.soc_drv);
+
+ free(empty_pmd0.soc_dev.addr.name);
+
+ printf("%s has been successful\n", __func__);
+ return 0;
+}
+
/* save real devices and drivers until the tests finishes */
struct soc_driver_list real_soc_driver_list =
TAILQ_HEAD_INITIALIZER(real_soc_driver_list);

+/* save real devices and drivers until the tests finishes */
+struct soc_device_list real_soc_device_list =
+ TAILQ_HEAD_INITIALIZER(real_soc_device_list);
+
static int test_soc_setup(void)
{
struct rte_soc_driver *drv;
+ struct rte_soc_device *dev;

/* no real drivers for the test */
while (!TAILQ_EMPTY(&soc_driver_list)) {
@@ -163,12 +280,20 @@ static int test_soc_setup(void)
TAILQ_INSERT_TAIL(&real_soc_driver_list, drv, next);
}

+ /* And, no real devices for the test */
+ while (!TAILQ_EMPTY(&soc_device_list)) {
+ dev = TAILQ_FIRST(&soc_device_list);
+ TAILQ_REMOVE(&soc_device_list, dev, next);
+ TAILQ_INSERT_TAIL(&real_soc_device_list, dev, next);
+ }
+
return 0;
}

static int test_soc_cleanup(void)
{
struct rte_soc_driver *drv;
+ struct rte_soc_device *dev;

/* bring back real drivers after the test */
while (!TAILQ_EMPTY(&real_soc_driver_list)) {
@@ -177,6 +302,13 @@ static int test_soc_cleanup(void)
rte_eal_soc_register(drv);
}

+ /* And, bring back real devices after the test */
+ while (!TAILQ_EMPTY(&real_soc_device_list)) {
+ dev = TAILQ_FIRST(&real_soc_device_list);
+ TAILQ_REMOVE(&real_soc_device_list, dev, next);
+ TAILQ_INSERT_TAIL(&soc_device_list, dev, next);
+ }
+
return 0;
}

@@ -192,6 +324,10 @@ test_soc(void)
if (test_register_unregister())
return -1;

+ /* Assuming test_register_unregister has succeeded */
+ if (test_soc_init_and_probe())
+ return -1;
+
if (test_soc_cleanup())
return -1;

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index de38848..3c407be 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -173,5 +173,9 @@ DPDK_16.11 {
rte_eal_soc_register;
rte_eal_soc_unregister;
rte_eal_soc_dump;
+ rte_eal_soc_match;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.07;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index 5dcddc5..bb87a67 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -36,6 +36,8 @@
#include <sys/queue.h>

#include <rte_log.h>
+#include <rte_common.h>
+#include <rte_soc.h>

#include "eal_private.h"

@@ -45,6 +47,213 @@ struct soc_driver_list soc_driver_list =
struct soc_device_list soc_device_list =
TAILQ_HEAD_INITIALIZER(soc_device_list);

+/* Default SoC device<->Driver match handler function */
+int
+rte_eal_soc_match(struct rte_soc_driver *drv, struct rte_soc_device *dev)
+{
+ int i, j;
+
+ RTE_VERIFY(drv != NULL && drv->id_table != NULL);
+ RTE_VERIFY(dev != NULL && dev->id != NULL);
+
+ for (i = 0; drv->id_table[i].compatible; ++i) {
+ const char *drv_compat = drv->id_table[i].compatible;
+
+ for (j = 0; dev->id[j].compatible; ++j) {
+ const char *dev_compat = dev->id[j].compatible;
+
+ if (!strcmp(drv_compat, dev_compat))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev)
+{
+ int ret = 1;
+
+ ret = drv->match_fn(drv, dev);
+ if (ret) {
+ RTE_LOG(DEBUG, EAL,
+ " match function failed, skipping\n");
+ return ret;
+ }
+
+ dev->driver = drv;
+ RTE_VERIFY(drv->devinit != NULL);
+ return drv->devinit(drv, dev);
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *drv = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(drv, &soc_driver_list, next) {
+ rc = rte_eal_soc_probe_one_driver(drv, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/* If the IDs match, call the devuninit() function of the driver. */
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
+ struct rte_soc_device *dev)
+{
+ int ret;
+
+ if ((drv == NULL) || (dev == NULL))
+ return -EINVAL;
+
+ ret = drv->match_fn(drv, dev);
+ if (ret) {
+ RTE_LOG(DEBUG, EAL,
+ " match function failed, skipping\n");
+ return ret;
+ }
+
+ RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+ dev->addr.name);
+
+ RTE_LOG(DEBUG, EAL, " remove driver: %s\n", drv->driver.name);
+
+ if (drv->devuninit && (drv->devuninit(dev) < 0))
+ return -1; /* negative value is an error */
+
+ /* clear driver structure */
+ dev->driver = NULL;
+
+ return 0;
+}
+
+/*
+ * Call the devuninit() function of all registered drivers for the given
+ * device if their IDs match.
+ *
+ * @return
+ * 0 when successful
+ * -1 if deinitialization fails
+ * 1 if no driver is found for this device.
+ */
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+ struct rte_soc_driver *dr = NULL;
+ int rc = 0;
+
+ if (dev == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dr, &soc_driver_list, next) {
+ rc = rte_eal_soc_detach_dev(dr, dev);
+ if (rc < 0)
+ /* negative value is an error */
+ return -1;
+ if (rc > 0)
+ /* positive value means driver doesn't support it */
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Detach device specified by its SoC address.
+ */
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_detach_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+
+ TAILQ_REMOVE(&soc_device_list, dev, next);
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n",
+ dev->addr.name);
+ return -1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ if (addr == NULL)
+ return -1;
+
+ /* unlike pci, in case of soc, it the responsibility of the soc driver
+ * to check during init whether device has been updated since last add.
+ */
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ if (rte_eal_compare_soc_addr(&dev->addr, addr))
+ continue;
+
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ goto err_return;
+ return 0;
+ }
+ return -1;
+
+err_return:
+ RTE_LOG(WARNING, EAL,
+ "Requested device %s cannot be used\n", addr->name);
+ return -1;
+}
+
+/*
+ * Scan the SoC devices and call the devinit() function for all registered
+ * drivers that have a matching entry in its id_table for discovered devices.
+ */
+int
+rte_eal_soc_probe(void)
+{
+ struct rte_soc_device *dev = NULL;
+ int ret = 0;
+
+ TAILQ_FOREACH(dev, &soc_device_list, next) {
+ ret = soc_probe_all_drivers(dev);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Requested device %s"
+ " cannot be used\n", dev->addr.name);
+ }
+
+ return 0;
+}
+
/* dump one device */
static int
soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
@@ -79,6 +288,12 @@ rte_eal_soc_dump(FILE *f)
void
rte_eal_soc_register(struct rte_soc_driver *driver)
{
+ /* For a valid soc driver, match and scan function
+ * should be provided.
+ */
+ RTE_VERIFY(driver != NULL);
+ RTE_VERIFY(driver->match_fn != NULL);
+ RTE_VERIFY(driver->scan_fn != NULL);
TAILQ_INSERT_TAIL(&soc_driver_list, driver, next);
}

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index c6f98eb..bfb49a2 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -97,6 +97,16 @@ typedef int (soc_devinit_t)(struct rte_soc_driver *, struct rte_soc_device *);
typedef int (soc_devuninit_t)(struct rte_soc_device *);

/**
+ * SoC device scan callback, called from rte_eal_soc_init.
+ */
+typedef void (soc_scan_t)(void);
+
+/**
+ * Custom device<=>driver match callback for SoC
+ */
+typedef int (soc_match_t)(struct rte_soc_driver *, struct rte_soc_device *);
+
+/**
* A structure describing a SoC driver.
*/
struct rte_soc_driver {
@@ -104,6 +114,8 @@ struct rte_soc_driver {
struct rte_driver driver; /**< Inherit core driver. */
soc_devinit_t *devinit; /**< Device initialization */
soc_devuninit_t *devuninit; /**< Device uninitialization */
+ soc_scan_t *scan_fn; /**< Callback for scanning SoC bus*/
+ soc_match_t *match_fn; /**< Callback to match dev<->drv */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
};

@@ -146,6 +158,45 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Default function for matching the Soc driver with device. Each driver can
+ * either use this function or define their own soc matching function.
+ * This function relies on the compatible string extracted from sysfs. But,
+ * a SoC might have different way of identifying its devices. Such SoC can
+ * override match_fn.
+ *
+ * @return
+ * 0 on success
+ * -1 when no match found
+ */
+int
+rte_eal_soc_match(struct rte_soc_driver *drv, struct rte_soc_device *dev);
+
+/**
+ * Probe SoC devices for registered drivers.
+ */
+int rte_eal_soc_probe(void);
+
+/**
+ * Probe the single SoC device.
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Scan the SoC devices and find the SoC device specified by the SoC
+ * address, then call the devuninit() function for registered driver
+ * that has a matching entry in its id_table for discovered device.
+ *
+ * @param addr
+ * The SoC address to close.
+ * @return
+ * - 0 on success.
+ * - Negative on error.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+/**
* Dump discovered SoC devices.
*/
void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 15c8c3d..147b601 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -70,6 +70,7 @@
#include <rte_cpuflags.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include <rte_common.h>
@@ -881,6 +882,10 @@ rte_eal_init(int argc, char **argv)
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");

+ /* Probe & Initialize SoC devices */
+ if (rte_eal_soc_probe())
+ rte_panic("Cannot probe SoC\n");
+
rte_eal_mcfg_complete();

return fctret;
diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c
index 04848b9..5f961c4 100644
--- a/lib/librte_eal/linuxapp/eal/eal_soc.c
+++ b/lib/librte_eal/linuxapp/eal/eal_soc.c
@@ -52,5 +52,21 @@
int
rte_eal_soc_init(void)
{
+ struct rte_soc_driver *drv;
+
+ /* for debug purposes, SoC can be disabled */
+ if (internal_config.no_soc)
+ return 0;
+
+ /* For each registered driver, call their scan routine to perform any
+ * custom scan for devices (for example, custom buses)
+ */
+ TAILQ_FOREACH(drv, &soc_driver_list, next) {
+ if (drv && drv->scan_fn) {
+ drv->scan_fn();
+ /* Ignore all errors from this */
+ }
+ }
+
return 0;
}
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index b9d1932..adcfe7d 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -179,5 +179,9 @@ DPDK_16.11 {
rte_eal_soc_register;
rte_eal_soc_unregister;
rte_eal_soc_dump;
+ rte_eal_soc_match;
+ rte_eal_soc_detach;
+ rte_eal_soc_probe;
+ rte_eal_soc_probe_one;

} DPDK_16.07;
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:51 UTC
Permalink
It is assumed that SoC Devices provided on command line are prefixed with
"soc:". This patch adds parse and attach support for such devices.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/eal_common_dev.c | 27 ++++++++++----
lib/librte_eal/common/eal_common_devargs.c | 17 +++++++++
lib/librte_eal/common/eal_common_soc.c | 55 ++++++++++++++++++++++++++---
lib/librte_eal/common/include/rte_devargs.h | 8 +++++
lib/librte_eal/common/include/rte_soc.h | 24 +++++++++++++
5 files changed, 119 insertions(+), 12 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index d1f0ad8..fbc4443 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -106,17 +106,23 @@ rte_eal_dev_init(void)

int rte_eal_dev_attach(const char *name, const char *devargs)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;

if (name == NULL || devargs == NULL) {
RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
return -EINVAL;
}

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_probe_one(&addr) < 0)
+ memset(&soc_addr, 0, sizeof(soc_addr));
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_probe_one(&soc_addr) < 0) {
+ free(soc_addr.name);
+ goto err;
+ }
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_probe_one(&pci_addr) < 0)
goto err;
-
} else {
if (rte_eal_vdev_init(name, devargs))
goto err;
@@ -131,15 +137,22 @@ err:

int rte_eal_dev_detach(const char *name)
{
- struct rte_pci_addr addr;
+ struct rte_soc_addr soc_addr;
+ struct rte_pci_addr pci_addr;

if (name == NULL) {
RTE_LOG(ERR, EAL, "Invalid device provided.\n");
return -EINVAL;
}

- if (eal_parse_pci_DomBDF(name, &addr) == 0) {
- if (rte_eal_pci_detach(&addr) < 0)
+ memset(&soc_addr, 0, sizeof(soc_addr));
+ if (rte_eal_parse_soc_spec(name, &soc_addr) == 0) {
+ if (rte_eal_soc_detach(&soc_addr) < 0) {
+ free(soc_addr.name);
+ goto err;
+ }
+ } else if (eal_parse_pci_DomBDF(name, &pci_addr) == 0) {
+ if (rte_eal_pci_detach(&pci_addr) < 0)
goto err;
} else {
if (rte_eal_vdev_uninit(name))
diff --git a/lib/librte_eal/common/eal_common_devargs.c b/lib/librte_eal/common/eal_common_devargs.c
index e403717..e1dae1a 100644
--- a/lib/librte_eal/common/eal_common_devargs.c
+++ b/lib/librte_eal/common/eal_common_devargs.c
@@ -41,6 +41,7 @@
#include <string.h>

#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_devargs.h>
#include "eal_private.h"

@@ -105,6 +106,14 @@ 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:
+ /* try to parse soc device with prefix "soc:" */
+ if (rte_eal_parse_soc_spec(buf, &devargs->soc.addr) != 0)
+ goto fail;
+ break;
+
case RTE_DEVTYPE_VIRTUAL:
/* save driver name */
ret = snprintf(devargs->virt.drv_name,
@@ -166,6 +175,14 @@ rte_eal_devargs_dump(FILE *f)
devargs->pci.addr.devid,
devargs->pci.addr.function,
devargs->args);
+ else if (devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ fprintf(f, " SoC whitelist %s %s\n",
+ devargs->soc.addr.name,
+ devargs->soc.addr.fdt_path);
+ else if (devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC)
+ fprintf(f, " SoC blacklist %s %s\n",
+ devargs->soc.addr.name,
+ devargs->soc.addr.fdt_path);
else if (devargs->type == RTE_DEVTYPE_VIRTUAL)
fprintf(f, " VIRTUAL %s %s\n",
devargs->virt.drv_name,
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index bb87a67..e9d413a 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -37,6 +37,8 @@

#include <rte_log.h>
#include <rte_common.h>
+#include <rte_devargs.h>
+#include <rte_eal.h>
#include <rte_soc.h>

#include "eal_private.h"
@@ -71,6 +73,21 @@ rte_eal_soc_match(struct rte_soc_driver *drv, struct rte_soc_device *dev)
}


+static struct rte_devargs *soc_devargs_lookup(struct rte_soc_device *dev)
+{
+ struct rte_devargs *devargs;
+
+ TAILQ_FOREACH(devargs, &devargs_list, next) {
+ if (devargs->type != RTE_DEVTYPE_BLACKLISTED_SOC &&
+ devargs->type != RTE_DEVTYPE_WHITELISTED_SOC)
+ continue;
+ if (!rte_eal_compare_soc_addr(&dev->addr, &devargs->soc.addr))
+ return devargs;
+ }
+
+ return NULL;
+}
+
static int
rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
struct rte_soc_device *dev)
@@ -84,6 +101,18 @@ rte_eal_soc_probe_one_driver(struct rte_soc_driver *drv,
return ret;
}

+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %d\n",
+ dev->addr.name, dev->device.numa_node);
+ RTE_LOG(DEBUG, EAL, " probe driver %s\n", drv->driver.name);
+
+ /* no initialization when blacklisted, return without error */
+ if (dev->device.devargs != NULL
+ && dev->device.devargs->type == RTE_DEVTYPE_BLACKLISTED_SOC) {
+ RTE_LOG(DEBUG, EAL,
+ " device is blacklisted, skipping\n");
+ return ret;
+ }
+
dev->driver = drv;
RTE_VERIFY(drv->devinit != NULL);
return drv->devinit(drv, dev);
@@ -128,8 +157,8 @@ rte_eal_soc_detach_dev(struct rte_soc_driver *drv,
return ret;
}

- RTE_LOG(DEBUG, EAL, "SoC device %s\n",
- dev->addr.name);
+ RTE_LOG(DEBUG, EAL, "SoC device %s on NUMA socket %i\n",
+ dev->addr.name, dev->device.numa_node);

RTE_LOG(DEBUG, EAL, " remove driver: %s\n", drv->driver.name);

@@ -242,13 +271,29 @@ int
rte_eal_soc_probe(void)
{
struct rte_soc_device *dev = NULL;
+ struct rte_devargs *devargs = NULL;
int ret = 0;
+ int probe_all = 0;
+
+ if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_SOC) == 0)
+ probe_all = 1;

TAILQ_FOREACH(dev, &soc_device_list, next) {
- ret = soc_probe_all_drivers(dev);
+
+ /* set devargs in SoC structure */
+ devargs = soc_devargs_lookup(dev);
+ if (devargs != NULL)
+ dev->device.devargs = devargs;
+
+ /* probe all or only whitelisted devices */
+ if (probe_all)
+ ret = soc_probe_all_drivers(dev);
+ else if (devargs != NULL &&
+ devargs->type == RTE_DEVTYPE_WHITELISTED_SOC)
+ ret = soc_probe_all_drivers(dev);
if (ret < 0)
- rte_exit(EXIT_FAILURE, "Requested device %s"
- " cannot be used\n", dev->addr.name);
+ rte_exit(EXIT_FAILURE, "Requested device %s "
+ "cannot be used\n", dev->addr.name);
}

return 0;
diff --git a/lib/librte_eal/common/include/rte_devargs.h b/lib/librte_eal/common/include/rte_devargs.h
index 53c59f5..757320e 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,11 @@ struct rte_devargs {
/** PCI location. */
struct rte_pci_addr addr;
} pci;
+ /** Used if type is RTE_DEVTYPE_*_SOC. */
+ 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
index bfb49a2..0bbef7d 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -158,6 +158,30 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
}

/**
+ * Parse a specification of a soc device. The specification must differentiate
+ * a SoC device specification from the PCI bus and virtual devices. We assume
+ * a SoC specification starts with "soc:". The function allocates the name
+ * entry of the given addr.
+ *
+ * @return
+ * - 0 on success
+ * - 1 when not a SoC spec
+ * - -1 on failure
+ */
+static inline int
+rte_eal_parse_soc_spec(const char *spec, struct rte_soc_addr *addr)
+{
+ if (strstr(spec, "soc:") == spec) {
+ addr->name = strdup(spec + 4);
+ if (addr->name == NULL)
+ return -1;
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
* Default function for matching the Soc driver with device. Each driver can
* either use this function or define their own soc matching function.
* This function relies on the compatible string extracted from sysfs. But,
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:52 UTC
Permalink
The flags are copied from the PCI ones. They should be refactorized into a
general set of flags in the future.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/include/rte_soc.h | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 0bbef7d..93d3a2f 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -117,8 +117,18 @@ struct rte_soc_driver {
soc_scan_t *scan_fn; /**< Callback for scanning SoC bus*/
soc_match_t *match_fn; /**< Callback to match dev<->drv */
const struct rte_soc_id *id_table; /**< ID table, NULL terminated */
+ uint32_t drv_flags; /**< Control handling of device */
};

+/** Device needs to map its resources by EAL */
+#define RTE_SOC_DRV_NEED_MAPPING 0x0001
+/** Device needs to be unbound even if no module is provieded */
+#define RTE_SOC_DRV_FORCE_UNBIND 0x0004
+/** Device driver supports link state interrupt */
+#define RTE_SOC_DRV_INTR_LSC 0x0008
+/** Device driver supports detaching capability */
+#define RTE_SOC_DRV_DETACHABLE 0x0010
+
/**
* Utility function to write a SoC device name, this device name can later be
* used to retrieve the corresponding rte_soc_addr using above functions.
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:54 UTC
Permalink
It is not necessary to place the rte_pci_driver at the beginning
of the rte_eth_dev struct anymore as we use the container_of macro
to get the parent pointer.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 4 ++--
lib/librte_ether/rte_ethdev.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index d54ec9e..b10d985 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -242,7 +242,7 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,

int diag;

- eth_drv = (struct eth_driver *)pci_drv;
+ eth_drv = container_of(pci_drv, struct eth_driver, pci_drv);

rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
sizeof(ethdev_name));
@@ -303,7 +303,7 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
if (eth_dev == NULL)
return -ENODEV;

- eth_drv = (const struct eth_driver *)pci_dev->driver;
+ eth_drv = container_of(pci_dev->driver, struct eth_driver, pci_drv);

/* Invoke PMD device uninit function */
if (*eth_drv->eth_dev_uninit) {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 2a697ec..8320dc4 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1842,7 +1842,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
* Each Ethernet driver acts as a PCI driver and is represented by a generic
* *eth_driver* structure that holds:
*
- * - An *rte_pci_driver* structure (which must be the first field).
+ * - An *rte_pci_driver* structure.
*
* - The *eth_dev_init* function invoked for each matching PCI device.
*
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:53 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_eal/common/include/rte_soc.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 93d3a2f..aa4c678 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -53,6 +53,7 @@ extern "C" {
#include <rte_dev.h>
#include <rte_eal.h>
#include <rte_debug.h>
+#include <rte_interrupts.h>

extern struct soc_driver_list soc_driver_list;
/**< Global list of SoC Drivers */
@@ -81,6 +82,7 @@ struct rte_soc_device {
struct rte_device device; /**< Inherit code device */
struct rte_soc_addr addr; /**< SoC device Location */
struct rte_soc_id *id; /**< SoC device ID list */
+ struct rte_intr_handle intr_handle; /**< Interrupt handle */
struct rte_soc_driver *driver; /**< Associated driver */
};
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:55 UTC
Permalink
Now that different types of ethdev exist, check for presence of PCI dev
while copying out the info.
Similar would be done for SoC.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index b10d985..e9f5467 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -3200,6 +3200,8 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
return;
}

+ RTE_VERIFY(eth_dev->pci_dev != NULL);
+
eth_dev->data->dev_flags = 0;
if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:56 UTC
Permalink
We abstract access to the intr_handle here as we want to get
it either from the pci_dev or soc_dev.

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e9f5467..104ea4a 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2526,6 +2526,17 @@ _rte_eth_dev_callback_process(struct rte_eth_dev *dev,
rte_spinlock_unlock(&rte_eth_dev_cb_lock);
}

+static inline
+struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return &dev->pci_dev->intr_handle;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
int
rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
{
@@ -2538,7 +2549,7 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);

dev = &rte_eth_devices[port_id];
- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
@@ -2598,7 +2609,7 @@ rte_eth_dev_rx_intr_ctl_q(uint8_t port_id, uint16_t queue_id,
return -EINVAL;
}

- intr_handle = &dev->pci_dev->intr_handle;
+ intr_handle = eth_dev_get_intr_handle(dev);
if (!intr_handle->intr_vec) {
RTE_PMD_DEBUG_TRACE("RX Intr vector unset\n");
return -EPERM;
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:57 UTC
Permalink
Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 104ea4a..4fa65ca 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -2568,6 +2568,17 @@ rte_eth_dev_rx_intr_ctl(uint8_t port_id, int epfd, int op, void *data)
return 0;
}

+static inline
+const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
+{
+ if (dev->pci_dev) {
+ return dev->driver->pci_drv.driver.name;
+ }
+
+ RTE_VERIFY(0);
+ return NULL;
+}
+
const struct rte_memzone *
rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
uint16_t queue_id, size_t size, unsigned align,
@@ -2575,9 +2586,11 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,
{
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
+ const char *drv_name;

+ drv_name = eth_dev_get_driver_name(dev);
snprintf(z_name, sizeof(z_name), "%s_%s_%d_%d",
- dev->driver->pci_drv.driver.name, ring_name,
+ drv_name, ring_name,
dev->data->port_id, queue_id);

mz = rte_memzone_lookup(z_name);
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:58 UTC
Permalink
- eth_driver/rte_eth_dev embeds rte_soc_driver/device for relating SoC
PMDs to ethernet devices.
- Add probe and remove functions linked to eth_dev_init/uninit

Signed-off-by: Jan Viktorin <***@rehivetech.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
Signed-off-by: Hemant Agrawal <***@nxp.com>
---
lib/librte_ether/rte_ethdev.c | 129 ++++++++++++++++++++++++++++++++++++++++++
lib/librte_ether/rte_ethdev.h | 31 ++++++++++
2 files changed, 160 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 4fa65ca..b57d7b2 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -326,6 +326,101 @@ rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
}

int
+rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+
+ int diag;
+
+ eth_drv = container_of(soc_drv, struct eth_driver, soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocate(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENOMEM;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev->data->dev_private = rte_zmalloc(
+ "ethdev private structure",
+ eth_drv->dev_private_size,
+ RTE_CACHE_LINE_SIZE);
+ if (eth_dev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private port "
+ "data\n");
+ }
+ eth_dev->soc_dev = soc_dev;
+ eth_dev->driver = eth_drv;
+ eth_dev->data->rx_mbuf_alloc_failed = 0;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(eth_dev->link_intr_cbs));
+
+ /*
+ * Set the default MTU.
+ */
+ eth_dev->data->mtu = ETHER_MTU;
+
+ /* Invoke PMD device initialization function */
+ diag = (*eth_drv->eth_dev_init)(eth_dev);
+ if (diag == 0)
+ return 0;
+
+ RTE_PMD_DEBUG_TRACE("driver %s: eth_dev_init(%s) failed\n",
+ soc_drv->driver.name,
+ soc_dev->addr.name);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+ rte_eth_dev_release_port(eth_dev);
+ return diag;
+}
+
+int
+rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct eth_driver *eth_drv;
+ struct rte_eth_dev *eth_dev;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, ethdev_name,
+ sizeof(ethdev_name));
+
+ eth_dev = rte_eth_dev_allocated(ethdev_name);
+ if (eth_dev == NULL)
+ return -ENODEV;
+
+ eth_drv = container_of(soc_dev->driver, struct eth_driver, soc_drv);
+
+ /* Invoke PMD device uninit function */
+ if (*eth_drv->eth_dev_uninit) {
+ ret = (*eth_drv->eth_dev_uninit)(eth_dev);
+ if (ret)
+ return ret;
+ }
+
+ /* free ether device */
+ rte_eth_dev_release_port(eth_dev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ eth_dev->soc_dev = NULL;
+ eth_dev->driver = NULL;
+ eth_dev->data = NULL;
+
+ return 0;
+}
+
+
+int
rte_eth_dev_is_valid_port(uint8_t port_id)
{
if (port_id >= RTE_MAX_ETHPORTS ||
@@ -1555,6 +1650,7 @@ rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
dev_info->pci_dev = dev->pci_dev;
+ dev_info->soc_dev = dev->soc_dev;
dev_info->driver_name = dev->data->drv_name;
dev_info->nb_rx_queues = dev->data->nb_rx_queues;
dev_info->nb_tx_queues = dev->data->nb_tx_queues;
@@ -2530,8 +2626,13 @@ static inline
struct rte_intr_handle *eth_dev_get_intr_handle(struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return &dev->pci_dev->intr_handle;
}
+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return &dev->soc_dev->intr_handle;
+ }

RTE_VERIFY(0);
return NULL;
@@ -2572,9 +2673,15 @@ static inline
const char *eth_dev_get_driver_name(const struct rte_eth_dev *dev)
{
if (dev->pci_dev) {
+ RTE_VERIFY(dev->soc_dev == NULL);
return dev->driver->pci_drv.driver.name;
}

+ if (dev->soc_dev) {
+ RTE_VERIFY(dev->pci_dev == NULL);
+ return dev->driver->soc_drv.driver.name;
+ }
+
RTE_VERIFY(0);
return NULL;
}
@@ -3237,6 +3344,28 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev, struct rte_pci_device *pci_de
eth_dev->data->drv_name = pci_dev->driver->driver.name;
}

+void
+rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev)
+{
+ if ((eth_dev == NULL) || (soc_dev == NULL)) {
+ RTE_PMD_DEBUG_TRACE("NULL pointer eth_dev=%p soc_dev=%p\n",
+ eth_dev, soc_dev);
+ return;
+ }
+
+ RTE_VERIFY(eth_dev->soc_dev != NULL);
+
+ eth_dev->data->dev_flags = 0;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_INTR_LSC)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+ if (soc_dev->driver->drv_flags & RTE_SOC_DRV_DETACHABLE)
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
+
+ eth_dev->data->numa_node = soc_dev->device.numa_node;
+ eth_dev->data->drv_name = soc_dev->driver->driver.name;
+}
+
int
rte_eth_dev_l2_tunnel_eth_type_conf(uint8_t port_id,
struct rte_eth_l2_tunnel_conf *l2_tunnel)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 8320dc4..4ae22e9 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -180,6 +180,7 @@ extern "C" {
#include <rte_log.h>
#include <rte_interrupts.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_dev.h>
#include <rte_devargs.h>
#include "rte_ether.h"
@@ -870,6 +871,7 @@ struct rte_eth_conf {
*/
struct rte_eth_dev_info {
struct rte_pci_device *pci_dev; /**< Device PCI information. */
+ struct rte_soc_device *soc_dev; /**< Device SoC information. */
const char *driver_name; /**< Device Driver name. */
unsigned int if_index; /**< Index to bound host interface, or 0 if none.
Use if_indextoname() to translate into an interface name. */
@@ -1619,6 +1621,7 @@ struct rte_eth_dev {
const struct eth_driver *driver;/**< Driver for this device */
const struct eth_dev_ops *dev_ops; /**< Functions exported by PMD */
struct rte_pci_device *pci_dev; /**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev; /**< SoC info. supplied by probing */
/** User application callbacks for NIC interrupts */
struct rte_eth_dev_cb_list link_intr_cbs;
/**
@@ -1852,6 +1855,7 @@ typedef int (*eth_dev_uninit_t)(struct rte_eth_dev *eth_dev);
*/
struct eth_driver {
struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is also a SoC driver. */
eth_dev_init_t eth_dev_init; /**< Device init function. */
eth_dev_uninit_t eth_dev_uninit; /**< Device uninit function. */
unsigned int dev_private_size; /**< Size of device private data. */
@@ -4244,6 +4248,20 @@ void rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
struct rte_pci_device *pci_dev);

/**
+ * Copy SoC device info to the Ethernet device data.
+ *
+ * @param eth_dev
+ * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
+ * @param soc_dev
+ * The *soc_dev* pointer is the address of the *rte_soc_device* structure.
+ *
+ * @return
+ * - 0 on success, negative on error
+ */
+void rte_eth_copy_soc_info(struct rte_eth_dev *eth_dev,
+ struct rte_soc_device *soc_dev);
+
+/**
* Create memzone for HW rings.
* malloc can't be used as the physical address is needed.
* If the memzone is already created, then this function returns a ptr
@@ -4356,6 +4374,19 @@ int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a ethdev
+ * interface.
+ */
+int rte_eth_dev_soc_remove(struct rte_soc_device *soc_dev);
+
#ifdef __cplusplus
}
#endif
--
2.7.4
Shreyansh Jain
2016-09-09 08:43:59 UTC
Permalink
- rte_cryptodev_driver/rte_cryptodev_dev embeds rte_soc_driver/device for
linking SoC PMDs to crypto devices.
- Add probe and remove functions linked

Signed-off-by: Hemant Agrawal <***@nxp.com>
Signed-off-by: Shreyansh Jain <***@nxp.com>
---
lib/librte_cryptodev/rte_cryptodev.c | 122 ++++++++++++++++++++++++-
lib/librte_cryptodev/rte_cryptodev.h | 3 +
lib/librte_cryptodev/rte_cryptodev_pmd.h | 18 +++-
lib/librte_cryptodev/rte_cryptodev_version.map | 3 +
4 files changed, 141 insertions(+), 5 deletions(-)

diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 2e17169..43e8685 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -423,7 +423,8 @@ rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,

int retval;

- cryptodrv = (struct rte_cryptodev_driver *)pci_drv;
+ cryptodrv = container_of(pci_drv, struct rte_cryptodev_driver,
+ pci_drv);
if (cryptodrv == NULL)
return -ENODEV;

@@ -490,7 +491,8 @@ rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
if (cryptodev == NULL)
return -ENODEV;

- cryptodrv = (const struct rte_cryptodev_driver *)pci_dev->driver;
+ cryptodrv = container_of(pci_dev->driver, struct rte_cryptodev_driver,
+ pci_drv);
if (cryptodrv == NULL)
return -ENODEV;

@@ -514,6 +516,111 @@ rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
return 0;
}

+
+int
+rte_cryptodev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev)
+{
+ struct rte_cryptodev_driver *cryptodrv;
+ struct rte_cryptodev *cryptodev;
+
+ char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+
+ int retval;
+
+ cryptodrv = container_of(soc_drv, struct rte_cryptodev_driver,
+ soc_drv);
+
+ rte_eal_soc_device_name(&soc_dev->addr, cryptodev_name,
+ sizeof(cryptodev_name));
+
+ cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name,
+ rte_socket_id());
+ if (cryptodev == NULL)
+ return -ENOMEM;
+
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ cryptodev->data->dev_private =
+ rte_zmalloc_socket(
+ "cryptodev private structure",
+ cryptodrv->dev_private_size,
+ RTE_CACHE_LINE_SIZE,
+ rte_socket_id());
+
+ if (cryptodev->data->dev_private == NULL)
+ rte_panic("Cannot allocate memzone for private "
+ "device data");
+ }
+
+ cryptodev->soc_dev = soc_dev;
+ cryptodev->driver = cryptodrv;
+
+ /* init user callbacks */
+ TAILQ_INIT(&(cryptodev->link_intr_cbs));
+
+ /* Invoke PMD device initialization function */
+ retval = (*cryptodrv->cryptodev_init)(cryptodrv, cryptodev);
+ if (retval == 0)
+ return 0;
+
+ CDEV_LOG_ERR("driver %s: cryptodev_init(%s) failed\n",
+ soc_drv->driver.name,
+ soc_dev->addr.name);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(cryptodev->data->dev_private);
+
+ cryptodev->attached = RTE_CRYPTODEV_DETACHED;
+ cryptodev_globals.nb_devs--;
+
+ return -ENXIO;
+}
+
+int
+rte_cryptodev_soc_remove(struct rte_soc_device *soc_dev)
+{
+ const struct rte_cryptodev_driver *cryptodrv;
+ struct rte_cryptodev *cryptodev;
+ char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
+ int ret;
+
+ if (soc_dev == NULL)
+ return -EINVAL;
+
+ rte_eal_soc_device_name(&soc_dev->addr, cryptodev_name,
+ sizeof(cryptodev_name));
+
+ cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
+ if (cryptodev == NULL)
+ return -ENODEV;
+
+ cryptodrv = container_of(soc_dev->driver,
+ struct rte_cryptodev_driver, soc_drv);
+ if (cryptodrv == NULL)
+ return -ENODEV;
+
+ /* Invoke PMD device uninit function */
+ if (*cryptodrv->cryptodev_uninit) {
+ ret = (*cryptodrv->cryptodev_uninit)(cryptodrv, cryptodev);
+ if (ret)
+ return ret;
+ }
+
+ /* free crypto device */
+ rte_cryptodev_pmd_release_device(cryptodev);
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(cryptodev->data->dev_private);
+
+ cryptodev->pci_dev = NULL;
+ cryptodev->soc_dev = NULL;
+ cryptodev->driver = NULL;
+ cryptodev->data = NULL;
+
+ return 0;
+}
+
uint16_t
rte_cryptodev_queue_pair_count(uint8_t dev_id)
{
@@ -869,8 +976,15 @@ rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
(*dev->dev_ops->dev_infos_get)(dev, dev_info);

dev_info->pci_dev = dev->pci_dev;
- if (dev->driver)
- dev_info->driver_name = dev->driver->pci_drv.driver.name;
+ dev_info->soc_dev = dev->soc_dev;
+ if (dev->driver) {
+ if (dev->soc_dev)
+ dev_info->driver_name
+ = dev->driver->soc_drv.driver.name;
+ else
+ dev_info->driver_name
+ = dev->driver->pci_drv.driver.name;
+ }
}


diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 13f46e4..d10f62e 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -231,6 +231,7 @@ struct rte_cryptodev_info {
const char *driver_name; /**< Driver name. */
enum rte_cryptodev_type dev_type; /**< Device type */
struct rte_pci_device *pci_dev; /**< PCI information. */
+ struct rte_soc_device *soc_dev; /**< SoC information. */

uint64_t feature_flags; /**< Feature flags */

@@ -610,6 +611,8 @@ struct rte_cryptodev {
/**< Supported features */
struct rte_pci_device *pci_dev;
/**< PCI info. supplied by probing */
+ struct rte_soc_device *soc_dev;
+ /**< SoC info. supplied by probing/Scanning */

enum rte_cryptodev_type dev_type;
/**< Crypto device type */
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index 99fd69e..db1756e 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -48,6 +48,7 @@ extern "C" {

#include <rte_dev.h>
#include <rte_pci.h>
+#include <rte_soc.h>
#include <rte_malloc.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
@@ -129,7 +130,8 @@ typedef int (*cryptodev_uninit_t)(const struct rte_cryptodev_driver *drv,
* - The size of the private data to allocate for each matching device.
*/
struct rte_cryptodev_driver {
- struct rte_pci_driver pci_drv; /**< The PMD is also a PCI driver. */
+ struct rte_pci_driver pci_drv; /**< The PMD is PCI type driver. */
+ struct rte_soc_driver soc_drv; /**< The PMD is SoC type driver. */
unsigned dev_private_size; /**< Size of device private data. */

cryptodev_init_t cryptodev_init; /**< Device init function. */
@@ -517,6 +519,20 @@ int rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,
*/
int rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev);

+/**
+ * Wrapper for use by SoC drivers as a .devinit function to attach to a
+ * cryptodev interface.
+ */
+int rte_cryptodev_soc_probe(struct rte_soc_driver *soc_drv,
+ struct rte_soc_device *soc_dev);
+
+/**
+ * Wrapper for use by SoC drivers as a .devuninit function to detach a
+ * cryptodev interface.
+ */
+int rte_cryptodev_soc_remove(struct rte_soc_device *soc_dev);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 9627ac4..d81073e 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -44,4 +44,7 @@ DPDK_16.11 {

rte_cryptodev_pci_probe;
rte_cryptodev_pci_remove;
+ rte_cryptodev_soc_probe;
+ rte_cryptodev_soc_remove;
+
} DPDK_16.07;
--
2.7.4
Hunt, David
2016-09-15 12:56:11 UTC
Permalink
Shreyansh, Jan, Hemant,
Post by Shreyansh Jain
=============
This patch set is direct derivative of Jan's original series [1],[2].
- As this deviates substantially from original series, if need be I can
post it as a separate patch rather than v2. Please suggest.
- Also, there are comments on original v1 ([4]) which are _not_
incorporated in this series as they refer to section no more in new
version.
- This v3 version is based on the rte_driver/device patchset v9 [10].
That series introduced device structures (rte_driver/rte_device)
generalizing devices into PCI, VDEV, XXX. For the purpose of this
patchset, XXX=>SOC.
---snip---

FYI, I've reviewed this patch set, and it looks to me like there's
some very good work here. Each patch in the set builds nicely on the one
before, and logically introduces the changes one by one.

I've no functional suggestions as the implementation looks clean,
but I've one or two tiny suggestions on headers and error messages. I'll
add a reply to the relevant patches in the set.

Also, there's one or two issues thrown up by checkpatch, but I suspect
they're false positives, as I'm using the 4.6 kernel version.

Regards,
Dave
Continue reading on narkive:
Loading...