[RFC v2 11/16] bus/fslmc: release resources on scan failure

David Marchand david.marchand at redhat.com
Thu Sep 17 09:49:11 CEST 2026


In case of a single failure, all mapped memory, VFIO resources and
device pointers were left untouched.
When reaching one init failure during scan, unwind what had been done so
far.

Note: the mapping helper was ignoring the memory callback registration
failure, so it is kept as is.

Signed-off-by: David Marchand <david.marchand at redhat.com>
---
 drivers/bus/fslmc/fslmc_bus.c  | 38 +++++++++++------------
 drivers/bus/fslmc/fslmc_vfio.c | 56 +++++++++++++++++++++++++++++-----
 drivers/bus/fslmc/fslmc_vfio.h |  1 +
 3 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c
index 2f66484ad2..802617c5fe 100644
--- a/drivers/bus/fslmc/fslmc_bus.c
+++ b/drivers/bus/fslmc/fslmc_bus.c
@@ -341,23 +341,20 @@ rte_fslmc_scan(void)
 
 	/* Scan the DPRC container object */
 	ret = scan_one_fslmc_device(group_name);
-	if (ret != 0) {
-		/* Error in parsing directory - exit gracefully */
-		goto scan_fail_cleanup;
-	}
-
-	while ((entry = readdir(dir)) != NULL) {
-		if (entry->d_name[0] == '.' || entry->d_type != DT_DIR)
-			continue;
+	if (ret == 0) {
+		while ((entry = readdir(dir)) != NULL) {
+			if (entry->d_name[0] == '.' || entry->d_type != DT_DIR)
+				continue;
 
-		ret = scan_one_fslmc_device(entry->d_name);
-		if (ret != 0) {
-			/* Error in parsing directory - exit gracefully */
-			goto scan_fail_cleanup;
+			ret = scan_one_fslmc_device(entry->d_name);
+			if (ret != 0)
+				break;
 		}
 	}
 
 	closedir(dir);
+	if (ret != 0)
+		goto scan_fail;
 
 	DPAA2_BUS_INFO("FSLMC Bus scan completed");
 	/* If debugging is enabled, device list is dumped to log output */
@@ -375,13 +372,13 @@ rte_fslmc_scan(void)
 			rte_mbuf_dynfield_register(&dpaa2_seqn_dynfield_desc);
 		if (dpaa2_seqn_dynfield_offset < 0) {
 			DPAA2_BUS_ERR("Failed to register mbuf field for dpaa sequence number");
-			return 0;
+			goto scan_fail;
 		}
 
 		ret = fslmc_vfio_setup_group();
 		if (ret) {
 			DPAA2_BUS_ERR("Unable to setup VFIO %d", ret);
-			return 0;
+			goto scan_fail;
 		}
 
 		/* Map existing segments as well as, in case of hotpluggable memory,
@@ -392,14 +389,14 @@ rte_fslmc_scan(void)
 			if (ret) {
 				DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", ret);
 				DPAA2_BUS_ERR("FSLMC VFIO Mapping failed");
-				return 0;
+				goto vfio_close_group;
 			}
 		}
 
 		ret = fslmc_vfio_process_group();
 		if (ret) {
 			DPAA2_BUS_ERR("Unable to setup devices %d", ret);
-			return 0;
+			goto vfio_dma_unmap;
 		}
 	}
 
@@ -407,13 +404,16 @@ rte_fslmc_scan(void)
 
 	return 0;
 
-scan_fail_cleanup:
-	closedir(dir);
+vfio_dma_unmap:
+	fslmc_vfio_dmaunmap();
+vfio_close_group:
+	fslmc_vfio_close_group();
 
+scan_fail:
 	/* Remove all devices in the list */
 	RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus)
 		fslmc_bus_remove_device(dev);
-scan_fail:
+
 	DPAA2_BUS_DEBUG("FSLMC Bus Not Available. Skipping (%d)", ret);
 	/* Irrespective of failure, scan only return success */
 	return 0;
diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c
index 705f5aeffc..03cac79c50 100644
--- a/drivers/bus/fslmc/fslmc_vfio.c
+++ b/drivers/bus/fslmc/fslmc_vfio.c
@@ -1157,6 +1157,27 @@ fslmc_dmamap_seg(const struct rte_memseg_list *msl __rte_unused,
 	return ret;
 }
 
+static int
+fslmc_dmaunmap_seg(const struct rte_memseg_list *msl __rte_unused,
+		const struct rte_memseg *ms, void *arg)
+{
+	int *n_segs = arg;
+	int ret;
+
+	/* if IOVA address is invalid, skip */
+	if (ms->iova == RTE_BAD_IOVA)
+		return 0;
+
+	ret = fslmc_unmap_dma(ms->addr_64, ms->iova, ms->len);
+	if (ret)
+		DPAA2_BUS_ERR("Unable to VFIO unmap (addr=%p, len=%zu)",
+				ms->addr, ms->len);
+	else
+		(*n_segs)++;
+
+	return ret;
+}
+
 RTE_EXPORT_SYMBOL(rte_fslmc_vfio_mem_dmamap)
 int
 rte_fslmc_vfio_mem_dmamap(uint64_t vaddr, uint64_t iova, uint64_t size)
@@ -1180,10 +1201,8 @@ fslmc_vfio_dmamap(void)
 	rte_mcfg_mem_read_lock();
 
 	ret = rte_memseg_walk(fslmc_dmamap_seg, &i);
-	if (ret) {
-		rte_mcfg_mem_read_unlock();
-		return ret;
-	}
+	if (ret != 0)
+		goto unmap;
 
 	ret = rte_mem_event_callback_register("fslmc_memevent_clb",
 			fslmc_memevent_cb, NULL);
@@ -1196,12 +1215,33 @@ fslmc_vfio_dmamap(void)
 
 	DPAA2_BUS_DEBUG("Total %d segments found.", i);
 
-	/* Existing segments have been mapped and memory callback for hotplug
-	 * has been installed.
-	 */
+	/* Ignore callback handler registration failure */
+	ret = 0;
+
+unmap:
+	if (ret != 0) {
+		i = 0;
+		rte_memseg_walk(fslmc_dmaunmap_seg, &i);
+	}
+
 	rte_mcfg_mem_read_unlock();
 
-	return 0;
+	return ret;
+}
+
+int
+fslmc_vfio_dmaunmap(void)
+{
+	int i = 0, ret;
+
+	rte_mcfg_mem_read_lock();
+
+	rte_mem_event_callback_unregister("fslmc_memevent_clb", NULL);
+	ret = rte_memseg_walk(fslmc_dmaunmap_seg, &i);
+
+	rte_mcfg_mem_read_unlock();
+
+	return ret;
 }
 
 static int
diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h
index c995fd67b8..57fe7038de 100644
--- a/drivers/bus/fslmc/fslmc_vfio.h
+++ b/drivers/bus/fslmc/fslmc_vfio.h
@@ -60,4 +60,5 @@ int fslmc_vfio_close_group(void);
 char *fslmc_get_container(void);
 int fslmc_get_container_group(const char *group_name, int *gropuid);
 int fslmc_vfio_dmamap(void);
+int fslmc_vfio_dmaunmap(void);
 #endif /* _FSLMC_VFIO_H_ */
-- 
2.54.0



More information about the dev mailing list