aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-10-08 08:45:29 -0600
committerAlex Williamson <alex.williamson@redhat.com>2012-10-08 08:45:29 -0600
commit12af1344871aee4a8df011c3b0548f7c77332d54 (patch)
tree8c55332d36c5317e2ea18dec6ada2eb59cd3283b
parentaf6bc27e39fafadbc03c8876ffa95851c5869683 (diff)
vfio-pci: Unmap and retry DMA mapping
Occasionally we get regions added that overlap with existing mappings. These always seems to be in the VGA ROM range. VFIO returns EBUSY for these mapping attempts. We can try a little harder and assume that the latest mapping is correct by removing any overlapping ranges and retrying the original request. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r--hw/vfio_pci.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 2d89d171ee..7413f2d531 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -819,12 +819,19 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova,
map.flags |= VFIO_DMA_MAP_FLAG_WRITE;
}
- if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) {
- DPRINTF("VFIO_MAP_DMA: %d\n", -errno);
- return -errno;
+ /*
+ * Try the mapping, if it fails with EBUSY, unmap the region and try
+ * again. This shouldn't be necessary, but we sometimes see it in
+ * the the VGA ROM space.
+ */
+ if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 ||
+ (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 &&
+ ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) {
+ return 0;
}
- return 0;
+ DPRINTF("VFIO_MAP_DMA: %d\n", -errno);
+ return -errno;
}
static void vfio_listener_dummy1(MemoryListener *listener)