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 <[email protected]> --- 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

