diff options
-rw-r--r-- | include/libvfio-user.h | 8 | ||||
-rw-r--r-- | lib/dma.c | 21 | ||||
-rw-r--r-- | lib/dma.h | 4 | ||||
-rw-r--r-- | lib/libvfio-user.c | 9 |
4 files changed, 28 insertions, 14 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h index a5dcc75..28933a5 100644 --- a/include/libvfio-user.h +++ b/include/libvfio-user.h @@ -655,7 +655,9 @@ vfu_unmap_sg(vfu_ctx_t *vfu_ctx, const dma_sg_t *sg, struct iovec *iov, int cnt); /** - * Read from the dma region exposed by the client. + * Read from the dma region exposed by the client. This can be used as an + * alternative to vfu_map_sg(), if the region is not directly mappable, or DMA + * notification callbacks have not been provided. * * @vfu_ctx: the libvfio-user context * @sg: a DMA segment obtained from dma_addr_to_sg @@ -667,7 +669,9 @@ int vfu_dma_read(vfu_ctx_t *vfu_ctx, dma_sg_t *sg, void *data); /** - * Write to the dma region exposed by the client. + * Write to the dma region exposed by the client. This can be used as an + * alternative to vfu_map_sg(), if the region is not directly mappable, or DMA + * notification callbacks have not been provided. * * @vfu_ctx: the libvfio-user context * @sg: a DMA segment obtained from dma_addr_to_sg @@ -154,7 +154,7 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma, continue; } - err = dma_unregister(data, ®ion->info); + err = dma_unregister == NULL ? 0 : dma_unregister(data, ®ion->info); if (err != 0) { err = errno; vfu_log(dma->vfu_ctx, LOG_ERR, @@ -178,7 +178,9 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma, } void -dma_controller_remove_regions(dma_controller_t *dma) +dma_controller_remove_all_regions(dma_controller_t *dma, + vfu_dma_unregister_cb_t *dma_unregister, + void *data) { int i; @@ -186,6 +188,7 @@ dma_controller_remove_regions(dma_controller_t *dma) for (i = 0; i < dma->nregions; i++) { dma_memory_region_t *region = &dma->regions[i]; + int err; vfu_log(dma->vfu_ctx, LOG_DEBUG, "removing DMA region " "iova=[%p, %p) vaddr=%p mapping=[%p, %p)", @@ -193,6 +196,14 @@ dma_controller_remove_regions(dma_controller_t *dma) region->info.vaddr, region->info.mapping.iov_base, iov_end(®ion->info.mapping)); + err = dma_unregister == NULL ? 0 : dma_unregister(data, ®ion->info); + if (err != 0) { + err = errno; + vfu_log(dma->vfu_ctx, LOG_ERR, + "failed to dma_unregister() DMA region [%p, %p): %m", + region->info.iova.iov_base, iov_end(®ion->info.iova)); + } + if (region->info.vaddr != NULL) { dma_controller_unmap_region(dma, region); } else { @@ -207,11 +218,7 @@ dma_controller_remove_regions(dma_controller_t *dma) void dma_controller_destroy(dma_controller_t *dma) { - if (dma == NULL) { - return; - } - - dma_controller_remove_regions(dma); + assert(dma->nregions == 0); free(dma); } @@ -102,7 +102,9 @@ dma_controller_t * dma_controller_create(vfu_ctx_t *vfu_ctx, int max_regions); void -dma_controller_remove_regions(dma_controller_t *dma); +dma_controller_remove_all_regions(dma_controller_t *dma, + vfu_dma_unregister_cb_t *dma_unregister, + void *data); void dma_controller_destroy(dma_controller_t *dma); diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index 92c1724..88135f2 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -1086,12 +1086,13 @@ vfu_reset_ctx(vfu_ctx_t *vfu_ctx, const char *reason) { vfu_log(vfu_ctx, LOG_INFO, "%s: %s", __func__, reason); - if (vfu_ctx->reset != NULL) { - vfu_ctx->reset(vfu_ctx, VFU_RESET_LOST_CONN); + if (vfu_ctx->dma != NULL) { + dma_controller_remove_all_regions(vfu_ctx->dma, vfu_ctx->dma_unregister, + vfu_ctx); } - if (vfu_ctx->dma != NULL) { - dma_controller_remove_regions(vfu_ctx->dma); + if (vfu_ctx->reset != NULL) { + vfu_ctx->reset(vfu_ctx, VFU_RESET_LOST_CONN); } if (vfu_ctx->irqs != NULL) { |