iommu/virtio: Return size mapped for a detached domain
authorJean-Philippe Brucker <jean-philippe@linaro.org>
Mon, 15 May 2023 11:39:50 +0000 (12:39 +0100)
committerJoerg Roedel <jroedel@suse.de>
Tue, 23 May 2023 06:19:03 +0000 (08:19 +0200)
When map() is called on a detached domain, the domain does not exist in
the device so we do not send a MAP request, but we do update the
internal mapping tree, to be replayed on the next attach. Since this
constitutes a successful iommu_map() call, return *mapped in this case
too.

Fixes: 7e62edd7a33a ("iommu/virtio: Add map/unmap_pages() callbacks implementation")
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20230515113946.1017624-3-jean-philippe@linaro.org
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/virtio-iommu.c

index fd316a37d75620820a080c9386f5b7b2adabd7f6..3551ed057774e648311f8c3f8ca71fb09f32161b 100644 (file)
@@ -833,25 +833,26 @@ static int viommu_map_pages(struct iommu_domain *domain, unsigned long iova,
        if (ret)
                return ret;
 
-       map = (struct virtio_iommu_req_map) {
-               .head.type      = VIRTIO_IOMMU_T_MAP,
-               .domain         = cpu_to_le32(vdomain->id),
-               .virt_start     = cpu_to_le64(iova),
-               .phys_start     = cpu_to_le64(paddr),
-               .virt_end       = cpu_to_le64(end),
-               .flags          = cpu_to_le32(flags),
-       };
-
-       if (!vdomain->nr_endpoints)
-               return 0;
+       if (vdomain->nr_endpoints) {
+               map = (struct virtio_iommu_req_map) {
+                       .head.type      = VIRTIO_IOMMU_T_MAP,
+                       .domain         = cpu_to_le32(vdomain->id),
+                       .virt_start     = cpu_to_le64(iova),
+                       .phys_start     = cpu_to_le64(paddr),
+                       .virt_end       = cpu_to_le64(end),
+                       .flags          = cpu_to_le32(flags),
+               };
 
-       ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
-       if (ret)
-               viommu_del_mappings(vdomain, iova, end);
-       else if (mapped)
+               ret = viommu_send_req_sync(vdomain->viommu, &map, sizeof(map));
+               if (ret) {
+                       viommu_del_mappings(vdomain, iova, end);
+                       return ret;
+               }
+       }
+       if (mapped)
                *mapped = size;
 
-       return ret;
+       return 0;
 }
 
 static size_t viommu_unmap_pages(struct iommu_domain *domain, unsigned long iova,