Scan for bus discovers the devices available on the bus and adds them
to a bus specific device list. Each bus mandatorily implements this
method.

Test cases for Bus are also updated by this patch.

Signed-off-by: Shreyansh Jain <shreyansh.j...@nxp.com>
Reviewed-by: Ferruh Yigit <ferruh.yi...@intel.com>
---
 app/test/test_bus.c                     | 175 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   2 +
 lib/librte_eal/common/include/rte_bus.h |  14 +++
 3 files changed, 191 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 9680bac..0b6d011 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -106,10 +106,26 @@ struct dummy_bus_map {
 struct rte_bus_list orig_bus_list =
        TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+static int scan_fn_for_busA(void);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+static int scan_fn_for_busB(void);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+
 struct dummy_bus busA = {
        .name = "busA_impl", /* busA */
        .bus = {
                .name = "busA",
+               .scan = scan_fn_for_busA,
        },
 };
 
@@ -117,6 +133,7 @@ struct dummy_bus busB = {
        .name = "busB_impl", /* busB */
        .bus = {
                .name = "busB",
+               .scan = scan_fn_for_busB,
        },
 };
 
@@ -226,9 +243,81 @@ dump_device_tree(void)
        printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the bus_map and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that bus_map list, register.
+ *
+ * @param bus
+ *     bus to scan againt test entry
+ * @return
+ *     0 for successful scan, even if no devices are found
+ *     !0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+       int i = 0;
+       struct dummy_device *ddev = NULL;
+       struct dummy_bus_map *dbmap = NULL;
+       struct dummy_bus *db = NULL;
+
+       if (!bus)
+               return -1;
+
+       /* Extract the device tree node using the bus passed */
+       for (i = 0; bus_map[i].name; i++) {
+               if (!strcmp(bus_map[i].name, bus->name)) {
+                       dbmap = &bus_map[i];
+                       break;
+               }
+       }
+
+       if (!dbmap)
+               return -1;
+
+       db = dbmap->dbus;
+
+       /* For all the devices in the device tree (bus_map), add device */
+       for (i = 0; dbmap->ddevices[i]; i++) {
+               ddev = dbmap->ddevices[i];
+               TAILQ_INSERT_TAIL(&db->device_list, ddev, next);
+               ddev->dev.bus = bus;
+       }
+
+       return 0;
+}
+
+int
+scan_fn_for_busA(void) {
+       struct dummy_bus_map *dbm;
+
+       dbm = &bus_map[0];
+       while (dbm) {
+               if (strcmp(dbm->name, "busA") == 0)
+                       return generic_scan_fn(&dbm->dbus->bus);
+               dbm++;
+       }
+       return 1;
+}
+
+int
+scan_fn_for_busB(void) {
+       struct dummy_bus_map *dbm;
+
+       dbm = &bus_map[0];
+       while (dbm) {
+               if (strcmp(dbm->name, "busB") == 0)
+                       return generic_scan_fn(&dbm->dbus->bus);
+               dbm++;
+       }
+       return 1;
+}
+
 static int
 test_bus_setup(void)
 {
+       int i = 0;
        struct rte_bus *bus_p = NULL;
 
        /* Preserve the original bus list before executing test */
@@ -238,6 +327,13 @@ test_bus_setup(void)
                TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
        }
 
+       /* Initialize the bus lists */
+       for (i = 0; bus_map[i].name; i++) {
+               TAILQ_INIT(&bus_map[i].dbus->device_list);
+               TAILQ_INIT(&bus_map[i].dbus->driver_list);
+       }
+
+       dump_device_tree();
        return 0;
 }
 
@@ -336,6 +432,79 @@ test_bus_unregistration(void)
        return 0;
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+       int i;
+       struct rte_bus *bus = NULL;
+       struct dummy_device *ddev;
+       struct dummy_bus *dbus;
+
+       for (i = 0; bus_map[i].name; i++) {
+               bus = &(bus_map[i].dbus->bus);
+               if (!bus) {
+                       printf("Unable to find bus (%s)\n",
+                              bus_map[i].name);
+                       return -1;
+               }
+
+               dbus = container_of(bus, struct dummy_bus, bus);
+               /* For bus 'bus', unregister all devices */
+               TAILQ_FOREACH(ddev, &dbus->device_list, next) {
+                       TAILQ_REMOVE(&dbus->device_list, ddev, next);
+               }
+       }
+
+       for (i = 0; bus_map[i].name; i++) {
+               bus = &(bus_map[i].dbus->bus);
+               dbus = container_of(bus, struct dummy_bus, bus);
+
+               if (!TAILQ_EMPTY(&dbus->device_list)) {
+                       printf("Unable to remove all devices on bus (%s)\n",
+                              bus->name);
+                       return -1;
+               }
+       }
+
+       /* All devices from all buses have been removed */
+       printf("All devices on all buses unregistered.\n");
+       dump_device_tree();
+
+       return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *     0 for successful scan
+ *     !0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+       int ret;
+       struct rte_bus *bus;
+
+       TAILQ_FOREACH(bus, &rte_bus_list, next) {
+               /* Call the scan function for each bus */
+               ret = bus->scan();
+               if (ret) {
+                       printf("Scan of buses failed.\n");
+                       return -1;
+               }
+       }
+
+       printf("Scan of all buses completed.\n");
+       dump_device_tree();
+
+       return 0;
+}
+
+
 int
 test_bus(void)
 {
@@ -346,6 +515,12 @@ test_bus(void)
        if (test_bus_registration())
                return -1;
 
+       if (test_bus_scan())
+               return -1;
+
+       if (test_device_unregistration_on_bus())
+               return -1;
+
        if (test_bus_unregistration())
                return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c 
b/lib/librte_eal/common/eal_common_bus.c
index 49b3516..d5d6beb 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -50,6 +50,8 @@ rte_bus_register(struct rte_bus *bus)
 {
        RTE_VERIFY(bus);
        RTE_VERIFY(bus->name && strlen(bus->name));
+       /* A bus should mandatorily have the scan implemented */
+       RTE_VERIFY(bus->scan);
 
        TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
        RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
diff --git a/lib/librte_eal/common/include/rte_bus.h 
b/lib/librte_eal/common/include/rte_bus.h
index 204e576..ba7d866 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -60,11 +60,25 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 extern struct rte_bus_list rte_bus_list;
 
 /**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @return
+ *     0 for successful scan
+ *     <0 for unsuccessful scan with error value
+ */
+typedef int (*rte_bus_scan_t)(void);
+
+/**
  * A structure describing a generic bus.
  */
 struct rte_bus {
        TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
        const char *name;            /**< Name of the bus */
+       rte_bus_scan_t scan;         /**< Scan for devices attached to bus */
 };
 
 /**
-- 
2.7.4

Reply via email to