drm/virtio: Improve DMA API usage for shmem BOs

DRM API requires the DRM's driver to be backed with the device that can
be used for generic DMA operations. The VirtIO-GPU device can't perform
DMA operations if it uses PCI transport because PCI device driver creates
a virtual VirtIO-GPU device that isn't associated with the PCI. Use PCI's
GPU device for the DRM's device instead of the VirtIO-GPU device and drop
DMA-related hacks from the VirtIO-GPU driver.

Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-8-dmitry.osipenko@collabora.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Dmitry Osipenko
2022-06-30 23:07:24 +03:00
committed by Gerd Hoffmann
parent e7fef09233
commit b5c9ed70d1
5 changed files with 32 additions and 99 deletions

View File

@@ -67,21 +67,6 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
if (virtio_gpu_is_shmem(bo)) {
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
if (shmem->pages) {
if (shmem->mapped) {
dma_unmap_sgtable(vgdev->vdev->dev.parent,
shmem->pages, DMA_TO_DEVICE, 0);
shmem->mapped = 0;
}
sg_free_table(shmem->pages);
kfree(shmem->pages);
shmem->pages = NULL;
drm_gem_shmem_unpin(&bo->base);
}
drm_gem_shmem_free(&bo->base);
} else if (virtio_gpu_is_vram(bo)) {
struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
@@ -153,36 +138,18 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
unsigned int *nents)
{
bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
struct scatterlist *sg;
int si, ret;
struct sg_table *pages;
int si;
ret = drm_gem_shmem_pin(&bo->base);
if (ret < 0)
return -EINVAL;
pages = drm_gem_shmem_get_pages_sgt(&bo->base);
if (IS_ERR(pages))
return PTR_ERR(pages);
/*
* virtio_gpu uses drm_gem_shmem_get_sg_table instead of
* drm_gem_shmem_get_pages_sgt because virtio has it's own set of
* dma-ops. This is discouraged for other drivers, but should be fine
* since virtio_gpu doesn't support dma-buf import from other devices.
*/
shmem->pages = drm_gem_shmem_get_sg_table(&bo->base);
if (IS_ERR(shmem->pages)) {
drm_gem_shmem_unpin(&bo->base);
shmem->pages = NULL;
return PTR_ERR(shmem->pages);
}
if (use_dma_api) {
ret = dma_map_sgtable(vgdev->vdev->dev.parent,
shmem->pages, DMA_TO_DEVICE, 0);
if (ret)
return ret;
*nents = shmem->mapped = shmem->pages->nents;
} else {
*nents = shmem->pages->orig_nents;
}
if (use_dma_api)
*nents = pages->nents;
else
*nents = pages->orig_nents;
*ents = kvmalloc_array(*nents,
sizeof(struct virtio_gpu_mem_entry),
@@ -193,13 +160,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
}
if (use_dma_api) {
for_each_sgtable_dma_sg(shmem->pages, sg, si) {
for_each_sgtable_dma_sg(pages, sg, si) {
(*ents)[si].addr = cpu_to_le64(sg_dma_address(sg));
(*ents)[si].length = cpu_to_le32(sg_dma_len(sg));
(*ents)[si].padding = 0;
}
} else {
for_each_sgtable_sg(shmem->pages, sg, si) {
for_each_sgtable_sg(pages, sg, si) {
(*ents)[si].addr = cpu_to_le64(sg_phys(sg));
(*ents)[si].length = cpu_to_le32(sg->length);
(*ents)[si].padding = 0;