aboutsummaryrefslogtreecommitdiff
path: root/hw
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 /hw
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>
Diffstat (limited to 'hw')
-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)