[dpdk-dev,v6,2/8] test: add basic bus infrastructure tests

Message ID 1484581107-2025-3-git-send-email-shreyansh.jain@nxp.com
State Superseded, archived
Headers show

Checks

Context Check Description
ci/Intel compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Shreyansh Jain Jan. 16, 2017, 3:38 p.m.
Verification of bus registration, deregistration methods.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile                       |   2 +-
 app/test/test.h                         |   2 +
 app/test/test_bus.c                     | 359 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h |   3 +
 4 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

Patch

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@  SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@  int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..9680bac
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,359 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   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 NXP 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_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 2250269..fe0f69d 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@  extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * A structure describing a generic bus.
  */