[dpdk-dev] [RFC 7/7] app/test: add SoC infra probe/detach test

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


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 <viktorin at 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 dpdk at testdevice
+	uevent_create > dpdk at 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



More information about the dev mailing list