Commit b32233ac authored by Zack Rusin's avatar Zack Rusin
Browse files

drm/vmwgfx: Fix prime import/export



vmwgfx never supported prime import of external buffers. Furthermore the
driver exposes two different objects to userspace: vmw_surface's and
gem buffers but prime import/export only worked with vmw_surfaces.

Because gem buffers are used through the dumb_buffer interface this meant
that the driver created buffers couldn't have been prime exported or
imported.

Fix prime import/export. Makes IGT's kms_prime pass.

Signed-off-by: default avatarZack Rusin <zack.rusin@broadcom.com>
Fixes: 8afa13a0 ("drm/vmwgfx: Implement DRIVER_GEM")
Cc: <stable@vger.kernel.org> # v6.6+
Reviewed-by: default avatarMartin Krastev <martin.krastev@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412025511.78553-4-zack.rusin@broadcom.com
parent b6976f32
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
		.no_wait_gpu = false
	};
	u32 j, initial_line = dst_offset / dst_stride;
	struct vmw_bo_blit_line_data d;
	struct vmw_bo_blit_line_data d = {0};
	int ret = 0;
	struct page **dst_pages = NULL;
	struct page **src_pages = NULL;

	/* Buffer objects need to be either pinned or reserved: */
	if (!(dst->pin_count))
@@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
			return ret;
	}

	if (!src->ttm->pages && src->ttm->sg) {
		src_pages = kvmalloc_array(src->ttm->num_pages,
					   sizeof(struct page *), GFP_KERNEL);
		if (!src_pages)
			return -ENOMEM;
		ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
						 src->ttm->num_pages);
		if (ret)
			goto out;
	}
	if (!dst->ttm->pages && dst->ttm->sg) {
		dst_pages = kvmalloc_array(dst->ttm->num_pages,
					   sizeof(struct page *), GFP_KERNEL);
		if (!dst_pages) {
			ret = -ENOMEM;
			goto out;
		}
		ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
						 dst->ttm->num_pages);
		if (ret)
			goto out;
	}

	d.mapped_dst = 0;
	d.mapped_src = 0;
	d.dst_addr = NULL;
	d.src_addr = NULL;
	d.dst_pages = dst->ttm->pages;
	d.src_pages = src->ttm->pages;
	d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
	d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
	d.dst_num_pages = PFN_UP(dst->resource->size);
	d.src_num_pages = PFN_UP(src->resource->size);
	d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
@@ -504,6 +529,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
		kunmap_atomic(d.src_addr);
	if (d.dst_addr)
		kunmap_atomic(d.dst_addr);
	if (src_pages)
		kvfree(src_pages);
	if (dst_pages)
		kvfree(dst_pages);

	return ret;
}
+4 −3
Original line number Diff line number Diff line
@@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
{
	struct ttm_operation_ctx ctx = {
		.interruptible = params->bo_type != ttm_bo_type_kernel,
		.no_wait_gpu = false
		.no_wait_gpu = false,
		.resv = params->resv,
	};
	struct ttm_device *bdev = &dev_priv->bdev;
	struct drm_device *vdev = &dev_priv->drm;
@@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,

	vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
	ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
				   &vmw_bo->placement, 0, &ctx, NULL,
				   NULL, destroy);
				   &vmw_bo->placement, 0, &ctx,
				   params->sg, params->resv, destroy);
	if (unlikely(ret))
		return ret;

+2 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ struct vmw_bo_params {
	enum ttm_bo_type bo_type;
	size_t size;
	bool pin;
	struct dma_resv *resv;
	struct sg_table *sg;
};

/**
+1 −0
Original line number Diff line number Diff line
@@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {

	.prime_fd_to_handle = vmw_prime_fd_to_handle,
	.prime_handle_to_fd = vmw_prime_handle_to_fd,
	.gem_prime_import_sg_table = vmw_prime_import_sg_table,

	.fops = &vmwgfx_driver_fops,
	.name = VMWGFX_DRIVER_NAME,
+3 −0
Original line number Diff line number Diff line
@@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
				  struct drm_file *file_priv,
				  uint32_t handle, uint32_t flags,
				  int *prime_fd);
struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
						 struct dma_buf_attachment *attach,
						 struct sg_table *table);

/*
 * MemoryOBject management -  vmwgfx_mob.c
Loading