In case of a single failure, all mapped memory, VFIO resources and
device pointers were left untouched.
When reaching one init failure during probe, 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 <[email protected]>
---
Changes since RFC v2:
- rebased,

---
 drivers/bus/fslmc/fslmc_bus.c  | 10 ++++--
 drivers/bus/fslmc/fslmc_vfio.c | 56 +++++++++++++++++++++++++++++-----
 drivers/bus/fslmc/fslmc_vfio.h |  1 +
 3 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c
index 0600f1afd5..b3ebf41fd7 100644
--- a/drivers/bus/fslmc/fslmc_bus.c
+++ b/drivers/bus/fslmc/fslmc_bus.c
@@ -423,17 +423,23 @@ rte_fslmc_probe(struct rte_bus *bus)
                if (ret) {
                        DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", 
ret);
                        DPAA2_BUS_ERR("FSLMC VFIO Mapping failed");
-                       return ret;
+                       goto vfio_close_group;
                }
        }
 
        ret = fslmc_vfio_process_group();
        if (ret) {
                DPAA2_BUS_ERR("Unable to setup devices %d", ret);
-               return ret;
+               goto vfio_dma_unmap;
        }
 
        return rte_bus_generic_probe(bus);
+
+vfio_dma_unmap:
+       fslmc_vfio_dmaunmap();
+vfio_close_group:
+       fslmc_vfio_close_group();
+       return ret;
 }
 
 static bool
diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c
index 10efd98e7b..c0ecf84cc7 100644
--- a/drivers/bus/fslmc/fslmc_vfio.c
+++ b/drivers/bus/fslmc/fslmc_vfio.c
@@ -1168,6 +1168,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)
@@ -1191,10 +1212,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);
@@ -1207,12 +1226,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

Reply via email to