diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2018-08-29 14:20:26 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2018-09-05 08:26:26 +0200 |
commit | a3b815f09bb846255c458c181b8a5b1cc66891b4 (patch) | |
tree | 53aceaede9167dbb6abb93ad51a5620fff6d7d18 /drivers/gpu/drm/virtio/virtgpu_vq.c | |
parent | b3f13ec958a77497da76cc7a89d60b741b79ba22 (diff) | |
download | lwn-a3b815f09bb846255c458c181b8a5b1cc66891b4.tar.gz lwn-a3b815f09bb846255c458c181b8a5b1cc66891b4.zip |
drm/virtio: add iommu support.
Use the dma mapping api and properly add iommu mappings for
objects, unless virtio is in iommu quirk mode.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20180829122026.27012-3-kraxel@redhat.com
Diffstat (limited to 'drivers/gpu/drm/virtio/virtgpu_vq.c')
-rw-r--r-- | drivers/gpu/drm/virtio/virtgpu_vq.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index e23c1927722f..5784c3ea8767 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -424,7 +424,8 @@ void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev, } static void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev, - uint32_t resource_id) + uint32_t resource_id, + struct virtio_gpu_fence **fence) { struct virtio_gpu_resource_detach_backing *cmd_p; struct virtio_gpu_vbuffer *vbuf; @@ -435,7 +436,7 @@ static void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgde cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING); cmd_p->resource_id = cpu_to_le32(resource_id); - virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); } void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev, @@ -849,9 +850,10 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, uint32_t resource_id, struct virtio_gpu_fence **fence) { + bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev); struct virtio_gpu_mem_entry *ents; struct scatterlist *sg; - int si; + int si, nents; if (!obj->pages) { int ret; @@ -861,23 +863,33 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, return ret; } + if (use_dma_api) { + obj->mapped = dma_map_sg(vgdev->vdev->dev.parent, + obj->pages->sgl, obj->pages->nents, + DMA_TO_DEVICE); + nents = obj->mapped; + } else { + nents = obj->pages->nents; + } + /* gets freed when the ring has consumed it */ - ents = kmalloc_array(obj->pages->nents, - sizeof(struct virtio_gpu_mem_entry), + ents = kmalloc_array(nents, sizeof(struct virtio_gpu_mem_entry), GFP_KERNEL); if (!ents) { DRM_ERROR("failed to allocate ent list\n"); return -ENOMEM; } - for_each_sg(obj->pages->sgl, sg, obj->pages->nents, si) { - ents[si].addr = cpu_to_le64(sg_phys(sg)); + for_each_sg(obj->pages->sgl, sg, nents, si) { + ents[si].addr = cpu_to_le64(use_dma_api + ? sg_dma_address(sg) + : sg_phys(sg)); ents[si].length = cpu_to_le32(sg->length); ents[si].padding = 0; } virtio_gpu_cmd_resource_attach_backing(vgdev, resource_id, - ents, obj->pages->nents, + ents, nents, fence); obj->hw_res_handle = resource_id; return 0; @@ -886,7 +898,23 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *obj) { - virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle); + bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev); + struct virtio_gpu_fence *fence; + + if (use_dma_api && obj->mapped) { + /* detach backing and wait for the host process it ... */ + virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, &fence); + dma_fence_wait(&fence->f, true); + dma_fence_put(&fence->f); + + /* ... then tear down iommu mappings */ + dma_unmap_sg(vgdev->vdev->dev.parent, + obj->pages->sgl, obj->mapped, + DMA_TO_DEVICE); + obj->mapped = 0; + } else { + virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, NULL); + } } void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev, |