Refactor device filtering logic by splitting what was done in
fslmc_vfio_process_group().

Separate control devices from other bus devices.

During scan, do not add device to the control list unless needed
(wrt secondary process, blocklist ...). Yet, keep a special
case for MPORTAL/DPIO objects and filter them in a new
fslmc_filter_control_devices() helper.

This helper is also responsible for selecting the right MPORTAL/DPIO
objects depending on primary/secondary considerations.

As a consequence, fslmc_vfio_process_group() only handles IO
device init without having to care about skipping some device.

Finally, remove now dead code in fslmc_vfio_close_group() since
only used devices are left in the control and bus device lists.

Signed-off-by: David Marchand <[email protected]>
---
Changes since RFC v1:
- split DPAA2 devices in two lists, one for EAL and one for the internal
  devices initialisation. This new list is kept ordered,
- fixed regressions raised by Stephen AI review:
  - allowlist issue: internal devices must be exempted from allowlist
    in some cases, so I simply reproduced the existing custom logic,
  - device pruning with only one DPIO device,
  - (unused) MPORTAL objects kept in device list,

---
 drivers/bus/fslmc/fslmc_bus.c  | 202 ++++++++++++++++++++++++++++++--
 drivers/bus/fslmc/fslmc_vfio.c | 205 ++++++++-------------------------
 drivers/bus/fslmc/private.h    |   4 +
 3 files changed, 250 insertions(+), 161 deletions(-)

diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c
index 802617c5fe..4789ab0cf3 100644
--- a/drivers/bus/fslmc/fslmc_bus.c
+++ b/drivers/bus/fslmc/fslmc_bus.c
@@ -30,6 +30,15 @@
 struct rte_bus rte_fslmc_bus;
 static int fslmc_bus_device_count[DPAA2_DEVTYPE_MAX];
 
+/*
+ * Control devices (MPORTAL, IO, CON, CI, BPOOL, MUX, DPRC) are bus 
infrastructure,
+ * not regular devices. They are initialized during scan/setup and don't 
participate
+ * in normal probe/unplug. Keep them in a separate list to avoid interference 
with
+ * generic bus operations.
+ */
+struct fslmc_control_device_list fslmc_control_devices =
+       TAILQ_HEAD_INITIALIZER(fslmc_control_devices);
+
 #define DPAA2_SEQN_DYNFIELD_NAME "dpaa2_seqn_dynfield"
 RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset)
 int dpaa2_seqn_dynfield_offset = -1;
@@ -106,10 +115,44 @@ fslmc_bus_remove_device(struct rte_dpaa2_device *dev)
        fslmc_free_device(&dev->device);
 }
 
+static void
+insert_in_control_device_list(struct rte_dpaa2_device *dev)
+{
+       struct rte_device *rte_dev;
+       struct rte_device *prev;
+
+       prev = NULL;
+       TAILQ_FOREACH(rte_dev, &fslmc_control_devices, next) {
+               if (compare_dpaa2_devname(dev, RTE_BUS_DEVICE(rte_dev, *dev)) < 
0)
+                       break;
+               prev = rte_dev;
+       }
+
+       if (prev != NULL)
+               TAILQ_INSERT_AFTER(&fslmc_control_devices, prev, &dev->device, 
next);
+       else
+               TAILQ_INSERT_HEAD(&fslmc_control_devices, &dev->device, next);
+
+       if (dev->dev_type < DPAA2_DEVTYPE_MAX)
+               fslmc_bus_device_count[dev->dev_type]++;
+}
+
+void
+fslmc_remove_control_device(struct rte_dpaa2_device *dev)
+{
+       if (dev->dev_type < DPAA2_DEVTYPE_MAX)
+               fslmc_bus_device_count[dev->dev_type]--;
+
+       TAILQ_REMOVE(&fslmc_control_devices, &dev->device, next);
+       rte_intr_instance_free(dev->intr_handle);
+       free(dev);
+}
+
 static void
 dump_device_list(void)
 {
        struct rte_dpaa2_device *dev;
+       struct rte_device *rte_dev;
 
        /* Only if the log level has been set to Debugging, print list */
        if (rte_log_can_log(dpaa2_logtype_bus, RTE_LOG_DEBUG)) {
@@ -117,6 +160,11 @@ dump_device_list(void)
                RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
                        DPAA2_BUS_LOG(DEBUG, "\t\t%s", dev->device.name);
                }
+               DPAA2_BUS_LOG(DEBUG, "List of control devices:");
+               TAILQ_FOREACH(rte_dev, &fslmc_control_devices, next) {
+                       dev = RTE_BUS_DEVICE(rte_dev, struct rte_dpaa2_device);
+                       DPAA2_BUS_LOG(DEBUG, "\t\t%s", dev->device.name);
+               }
        }
 }
 
@@ -166,11 +214,39 @@ scan_one_fslmc_device(char *dev_name)
                dev_id = ptr + 1;
        }
 
-       /* For all other devices, we allocate rte_dpaa2_device.
-        * For those devices where there is no driver, probe would release
-        * the memory associated with the rte_dpaa2_device after necessary
-        * initialization.
+       /*
+        * DPAA2_MPORTAL and DPAA2_IO types are handled separately,
+        * see fslmc_filter_control_devices()
+        *
+        * Note: Only check for explicit blocklist (RTE_DEV_BLOCKED).
+        * Control objects (dpbp, dpcon, etc.) are required even in allowlist
+        * mode as they are initialized by fslmc_vfio_process_group(), not 
probed.
         */
+       if (dev_type != DPAA2_MPORTAL && dev_type != DPAA2_IO) {
+               struct rte_devargs *devargs = 
rte_bus_find_devargs(&rte_fslmc_bus, dev_name);
+
+               if (devargs && devargs->policy == RTE_DEV_BLOCKED) {
+                       DPAA2_BUS_DEBUG("Skipping blocklisted device (%s)", 
dev_name);
+                       return 0;
+               }
+       }
+
+       /* For secondary processes, control objects are not needed */
+       if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+               switch (dev_type) {
+               case DPAA2_ETH:
+               case DPAA2_CRYPTO:
+               case DPAA2_QDMA:
+               case DPAA2_IO:
+               case DPAA2_MPORTAL:
+               case DPAA2_DPRC:
+                       break;
+               default:
+                       DPAA2_BUS_DEBUG("Skipping device in secondary process 
(%s)", dev_name);
+                       return 0;
+               }
+       }
+
        dev = calloc(1, sizeof(struct rte_dpaa2_device));
        if (!dev) {
                DPAA2_BUS_ERR("Unable to allocate device object");
@@ -203,8 +279,16 @@ scan_one_fslmc_device(char *dev_name)
        dev->device.name = dev->name;
        dev->device.devargs = rte_bus_find_devargs(&rte_fslmc_bus, dev_name);
 
-       /* Add device in the fslmc device list */
-       insert_in_device_list(dev);
+       switch (dev_type) {
+       case DPAA2_ETH:
+       case DPAA2_CRYPTO:
+       case DPAA2_QDMA:
+               insert_in_device_list(dev);
+               break;
+       default:
+               insert_in_control_device_list(dev);
+               break;
+       }
 
        return 0;
 cleanup:
@@ -298,6 +382,97 @@ fslmc_dev_compare(const char *name1, const char *name2)
        return strncmp(devname1, devname2, sizeof(devname1));
 }
 
+static int
+fslmc_filter_control_devices(void)
+{
+       bool is_dpmcp_in_blocklist = false, is_dpio_in_blocklist = false;
+       int dpmcp_count = 0, dpio_count = 0;
+       struct rte_dpaa2_device *dev;
+       struct rte_device *rte_dev;
+       struct rte_device *tmp_dev;
+
+       /* Track MPORTAL/DPIO blocklists */
+       RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, tmp_dev) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               if (dev->dev_type != DPAA2_MPORTAL && dev->dev_type != DPAA2_IO)
+                       continue;
+               /* Only check for explicit blocklist, not allowlist */
+               if (dev->device.devargs && dev->device.devargs->policy == 
RTE_DEV_BLOCKED) {
+                       DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping", 
dev->device.name);
+                       if (dev->dev_type == DPAA2_MPORTAL)
+                               is_dpmcp_in_blocklist = true;
+                       else if (dev->dev_type == DPAA2_IO)
+                               is_dpio_in_blocklist = true;
+                       fslmc_remove_control_device(dev);
+                       continue;
+               }
+               if (dev->dev_type == DPAA2_MPORTAL)
+                       dpmcp_count++;
+               else if (dev->dev_type == DPAA2_IO)
+                       dpio_count++;
+       }
+
+       if (dpmcp_count == 0) {
+               DPAA2_BUS_ERR("No MC Portal device found");
+               return -ENODEV;
+       }
+
+       /* Automatic MPORTAL split: primary keeps first, secondary keeps last */
+       if (!is_dpmcp_in_blocklist) {
+               int current_device = 0;
+               int keep_index;
+
+               /* Check MPORTAL availability for secondary */
+               if (rte_eal_process_type() == RTE_PROC_SECONDARY && dpmcp_count 
< 2) {
+                       DPAA2_BUS_ERR("No MC Portal device found for 
secondary");
+                       return -ENODEV;
+               }
+
+               if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+                       keep_index = 0;
+               else
+                       keep_index = dpmcp_count - 1;
+
+               RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, 
tmp_dev) {
+                       dev = RTE_BUS_DEVICE(rte_dev, *dev);
+                       if (dev->dev_type != DPAA2_MPORTAL)
+                               continue;
+                       if (current_device != keep_index)
+                               fslmc_remove_control_device(dev);
+
+                       current_device++;
+                       if (current_device == dpmcp_count)
+                               break;
+               }
+       }
+
+       /* Automatic DPIO split: secondary keeps last only, primary removes 
last */
+       if (!is_dpio_in_blocklist && dpio_count > 1) {
+               int last_index = dpio_count - 1;
+               int current_device = 0;
+
+               RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, 
tmp_dev) {
+                       dev = RTE_BUS_DEVICE(rte_dev, *dev);
+                       if (dev->dev_type != DPAA2_IO)
+                               continue;
+
+                       if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
+                                       current_device != last_index) {
+                               fslmc_remove_control_device(dev);
+                       } else if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
+                                       current_device == last_index) {
+                               fslmc_remove_control_device(dev);
+                       }
+
+                       current_device++;
+                       if (current_device == dpio_count)
+                               break;
+               }
+       }
+
+       return 0;
+}
+
 static int
 rte_fslmc_scan(void)
 {
@@ -361,7 +536,7 @@ rte_fslmc_scan(void)
        dump_device_list();
 
        /* Bus initialization - only if devices were found */
-       if (!TAILQ_EMPTY(&rte_fslmc_bus.device_list)) {
+       if (!TAILQ_EMPTY(&rte_fslmc_bus.device_list) || 
!TAILQ_EMPTY(&fslmc_control_devices)) {
                static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc 
= {
                        .name = DPAA2_SEQN_DYNFIELD_NAME,
                        .size = sizeof(dpaa2_seqn_t),
@@ -393,6 +568,12 @@ rte_fslmc_scan(void)
                        }
                }
 
+               ret = fslmc_filter_control_devices();
+               if (ret) {
+                       DPAA2_BUS_ERR("Unable to filter control devices %d", 
ret);
+                       goto vfio_dma_unmap;
+               }
+
                ret = fslmc_vfio_process_group();
                if (ret) {
                        DPAA2_BUS_ERR("Unable to setup devices %d", ret);
@@ -410,6 +591,13 @@ rte_fslmc_scan(void)
        fslmc_vfio_close_group();
 
 scan_fail:
+       while (!TAILQ_EMPTY(&fslmc_control_devices)) {
+               struct rte_device *rte_dev = 
TAILQ_FIRST(&fslmc_control_devices);
+
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               fslmc_remove_control_device(dev);
+       }
+
        /* Remove all devices in the list */
        RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus)
                fslmc_bus_remove_device(dev);
diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c
index 03cac79c50..954167f452 100644
--- a/drivers/bus/fslmc/fslmc_vfio.c
+++ b/drivers/bus/fslmc/fslmc_vfio.c
@@ -1599,6 +1599,7 @@ int
 fslmc_vfio_close_group(void)
 {
        struct rte_dpaa2_device *dev;
+       struct rte_device *rte_dev;
        int vfio_group_fd;
        const char *group_name = fslmc_vfio_get_group_name();
 
@@ -1611,30 +1612,14 @@ fslmc_vfio_close_group(void)
                return -EIO;
        }
 
-       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
-               switch (dev->dev_type) {
-               case DPAA2_ETH:
-               case DPAA2_CRYPTO:
-               case DPAA2_QDMA:
-               case DPAA2_IO:
-                       fslmc_close_iodevices(dev, vfio_group_fd);
-                       break;
-               case DPAA2_CON:
-               case DPAA2_CI:
-               case DPAA2_BPOOL:
-               case DPAA2_MUX:
-                       if (rte_eal_process_type() == RTE_PROC_SECONDARY)
-                               continue;
-
-                       fslmc_close_iodevices(dev, vfio_group_fd);
-                       break;
-               case DPAA2_DPRTC:
-               default:
-                       DPAA2_BUS_DEBUG("Device cannot be closed: Not supported 
(%s)",
-                                       dev->device.name);
-               }
+       TAILQ_FOREACH(rte_dev, &fslmc_control_devices, next) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               fslmc_close_iodevices(dev, vfio_group_fd);
        }
 
+       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus)
+               fslmc_close_iodevices(dev, vfio_group_fd);
+
        fslmc_vfio_clear_group(vfio_group_fd);
 
        return 0;
@@ -1643,168 +1628,80 @@ fslmc_vfio_close_group(void)
 int
 fslmc_vfio_process_group(void)
 {
-       int ret;
-       int found_mportal = 0;
        struct rte_dpaa2_device *dev;
-       bool is_dpmcp_in_blocklist = false, is_dpio_in_blocklist = false;
-       int dpmcp_count = 0, dpio_count = 0, current_device;
-
-       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
-               if (dev->dev_type == DPAA2_MPORTAL) {
-                       dpmcp_count++;
-                       if (dev->device.devargs &&
-                           dev->device.devargs->policy == RTE_DEV_BLOCKED)
-                               is_dpmcp_in_blocklist = true;
-               }
-               if (dev->dev_type == DPAA2_IO) {
-                       dpio_count++;
-                       if (dev->device.devargs &&
-                           dev->device.devargs->policy == RTE_DEV_BLOCKED)
-                               is_dpio_in_blocklist = true;
-               }
-       }
-
-       /* Search the MCP as that should be initialized first. */
-       current_device = 0;
-       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
-               if (dev->dev_type == DPAA2_MPORTAL) {
-                       current_device++;
-                       if (dev->device.devargs &&
-                           dev->device.devargs->policy == RTE_DEV_BLOCKED) {
-                               DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping",
-                                             dev->device.name);
-                               fslmc_bus_remove_device(dev);
-                               continue;
-                       }
-
-                       if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
-                           !is_dpmcp_in_blocklist) {
-                               if (dpmcp_count == 1 ||
-                                   current_device != dpmcp_count) {
-                                       fslmc_bus_remove_device(dev);
-                                       continue;
-                               }
-                       }
-
-                       if (!found_mportal) {
-                               ret = fslmc_process_mcp(dev);
-                               if (ret) {
-                                       DPAA2_BUS_ERR("Unable to map MC 
Portal");
-                                       return ret;
-                               }
-                               found_mportal = 1;
-                       }
+       struct rte_device *rte_dev;
+       struct rte_device *tmp_dev;
+       int ret;
 
-                       fslmc_bus_remove_device(dev);
-                       /* Ideally there is only a single dpmcp, but in case
-                        * multiple exists, looping on remaining devices.
-                        */
+       /* Process MPORTAL - should be initialized first */
+       RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, tmp_dev) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               if (dev->dev_type != DPAA2_MPORTAL)
+                       continue;
+               ret = fslmc_process_mcp(dev);
+               if (ret) {
+                       DPAA2_BUS_ERR("Unable to map MC Portal");
+                       return ret;
                }
+               fslmc_remove_control_device(dev);
+               break;
        }
 
-       /* Cannot continue if there is not even a single mportal */
-       if (!found_mportal) {
-               DPAA2_BUS_ERR("No MC Portal device found. Not continuing");
-               return -EIO;
+       /* Remove any remaining MPORTAL devices */
+       RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, tmp_dev) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               if (dev->dev_type == DPAA2_MPORTAL)
+                       fslmc_remove_control_device(dev);
        }
 
-       /* Search for DPRC device next as it updates endpoint of
+       /* Process DPRC device next as it updates endpoint of
         * other devices.
         */
-       current_device = 0;
-       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
-               if (dev->dev_type == DPAA2_DPRC) {
-                       ret = fslmc_process_iodevices(dev);
-                       if (ret) {
-                               DPAA2_BUS_ERR("Unable to process dprc");
-                               return ret;
-                       }
-                       fslmc_bus_remove_device(dev);
+       RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, tmp_dev) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
+               if (dev->dev_type != DPAA2_DPRC)
+                       continue;
+               ret = fslmc_process_iodevices(dev);
+               if (ret) {
+                       DPAA2_BUS_ERR("Unable to process dprc");
+                       return ret;
                }
+               fslmc_remove_control_device(dev);
        }
 
-       current_device = 0;
-       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
-               if (dev->dev_type == DPAA2_IO)
-                       current_device++;
-               if (dev->device.devargs &&
-                   dev->device.devargs->policy == RTE_DEV_BLOCKED) {
-                       DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping",
-                                     dev->device.name);
-                       fslmc_bus_remove_device(dev);
-                       continue;
-               }
-               if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
-                   dev->dev_type != DPAA2_ETH &&
-                   dev->dev_type != DPAA2_CRYPTO &&
-                   dev->dev_type != DPAA2_QDMA &&
-                   dev->dev_type != DPAA2_IO) {
-                       fslmc_bus_remove_device(dev);
-                       continue;
-               }
+       /* Process remaining control devices */
+       RTE_TAILQ_FOREACH_SAFE(rte_dev, &fslmc_control_devices, next, tmp_dev) {
+               dev = RTE_BUS_DEVICE(rte_dev, *dev);
                switch (dev->dev_type) {
-               case DPAA2_ETH:
-               case DPAA2_CRYPTO:
-               case DPAA2_QDMA:
-                       ret = fslmc_process_iodevices(dev);
-                       if (ret) {
-                               DPAA2_BUS_DEBUG("Dev (%s) init failed",
-                                               dev->device.name);
-                               return ret;
-                       }
-                       break;
                case DPAA2_CON:
                case DPAA2_CI:
                case DPAA2_BPOOL:
                case DPAA2_DPRTC:
                case DPAA2_MUX:
-                       /* IN case of secondary processes, all control objects
-                        * like dpbp, dpcon, dpci are not initialized/required
-                        * - all of these are assumed to be initialized and made
-                        *   available by primary.
-                        */
-                       if (rte_eal_process_type() == RTE_PROC_SECONDARY)
-                               continue;
-
-                       /* Call the object creation routine and remove the
-                        * device entry from device list
-                        */
-                       ret = fslmc_process_iodevices(dev);
-                       if (ret) {
-                               DPAA2_BUS_DEBUG("Dev (%s) init failed",
-                                               dev->device.name);
-                               return ret;
-                       }
-
-                       break;
                case DPAA2_IO:
-                       if (!is_dpio_in_blocklist && dpio_count > 1) {
-                               if (rte_eal_process_type() == RTE_PROC_SECONDARY
-                                   && current_device != dpio_count) {
-                                       fslmc_bus_remove_device(dev);
-                                       break;
-                               }
-                               if (rte_eal_process_type() == RTE_PROC_PRIMARY
-                                   && current_device == dpio_count) {
-                                       fslmc_bus_remove_device(dev);
-                                       break;
-                               }
-                       }
-
                        ret = fslmc_process_iodevices(dev);
                        if (ret) {
                                DPAA2_BUS_DEBUG("Dev (%s) init failed",
                                                dev->device.name);
                                return ret;
                        }
-
                        break;
-               case DPAA2_UNKNOWN:
                default:
                        /* Unknown - ignore */
                        DPAA2_BUS_DEBUG("Found unknown device (%s)",
                                        dev->device.name);
-                       fslmc_bus_remove_device(dev);
+                       fslmc_remove_control_device(dev);
+                       break;
+               }
+       }
+
+       /* Process regular devices */
+       RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) {
+               ret = fslmc_process_iodevices(dev);
+               if (ret) {
+                       DPAA2_BUS_DEBUG("Dev (%s) init failed",
+                                       dev->device.name);
+                       return ret;
                }
        }
 
diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h
index 825a364f1b..064ffa9536 100644
--- a/drivers/bus/fslmc/private.h
+++ b/drivers/bus/fslmc/private.h
@@ -11,6 +11,10 @@
 
 extern struct rte_bus rte_fslmc_bus;
 
+RTE_TAILQ_HEAD(fslmc_control_device_list, rte_device);
+extern struct fslmc_control_device_list fslmc_control_devices;
+
 void fslmc_bus_remove_device(struct rte_dpaa2_device *dev);
+void fslmc_remove_control_device(struct rte_dpaa2_device *dev);
 
 #endif /* BUS_FSLMC_PRIVATE_H */
-- 
2.54.0

Reply via email to