aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libvfio-user.h8
-rw-r--r--lib/dma.c21
-rw-r--r--lib/dma.h4
-rw-r--r--lib/libvfio-user.c9
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
diff --git a/lib/dma.c b/lib/dma.c
index 2aad1a8..9b29cc9 100644
--- a/lib/dma.c
+++ b/lib/dma.c
@@ -154,7 +154,7 @@ MOCK_DEFINE(dma_controller_remove_region)(dma_controller_t *dma,
continue;
}
- err = dma_unregister(data, &region->info);
+ err = dma_unregister == NULL ? 0 : dma_unregister(data, &region->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(&region->info.mapping));
+ err = dma_unregister == NULL ? 0 : dma_unregister(data, &region->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(&region->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);
}
diff --git a/lib/dma.h b/lib/dma.h
index eb907e0..b9bf38e 100644
--- a/lib/dma.h
+++ b/lib/dma.h
@@ -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) {