Commit c67e6279 authored by Christian König's avatar Christian König
Browse files

drm/prime: split array import functions v4



Mapping the imported pages of a DMA-buf into an userspace process
doesn't work as expected.

But we have reoccurring requests on this approach, so split the
functions for this and  document that dma_buf_mmap() needs to be used
instead.

v2: split it into two functions
v3: rebased on latest changes
v4: update commit message a bit

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Acked-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/403838/
parent 18f7608a
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -918,7 +918,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device *bdev,
		goto release_sg;

	/* convert SG to linear array of pages and dma addresses */
	drm_prime_sg_to_page_addr_arrays(ttm->sg, NULL, gtt->ttm.dma_address,
	drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
				       ttm->num_pages);

	return 0;
@@ -1264,8 +1264,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev,
			ttm->sg = sgt;
		}

		drm_prime_sg_to_page_addr_arrays(ttm->sg, NULL,
						 gtt->ttm.dma_address,
		drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
					       ttm->num_pages);
		return 0;
	}
+39 −25
Original line number Diff line number Diff line
@@ -978,44 +978,58 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
EXPORT_SYMBOL(drm_gem_prime_import);

/**
 * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
 * drm_prime_sg_to_page_array - convert an sg table into a page array
 * @sgt: scatter-gather table to convert
 * @pages: optional array of page pointers to store the page array in
 * @addrs: optional array to store the dma bus address of each page
 * @max_entries: size of both the passed-in arrays
 * @pages: array of page pointers to store the pages in
 * @max_entries: size of the passed-in array
 *
 * Exports an sg table into an array of pages and addresses. This is currently
 * required by the TTM driver in order to do correct fault handling.
 * Exports an sg table into an array of pages.
 *
 * Drivers can use this in their &drm_driver.gem_prime_import_sg_table
 * implementation.
 * This function is deprecated and strongly discouraged to be used.
 * The page array is only useful for page faults and those can corrupt fields
 * in the struct page if they are not handled by the exporting driver.
 */
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
				     dma_addr_t *addrs, int max_entries)
int __deprecated drm_prime_sg_to_page_array(struct sg_table *sgt,
					    struct page **pages,
					    int max_entries)
{
	struct sg_dma_page_iter dma_iter;
	struct sg_page_iter page_iter;
	struct page **p = pages;
	dma_addr_t *a = addrs;

	if (pages) {
	for_each_sgtable_page(sgt, &page_iter, 0) {
		if (WARN_ON(p - pages >= max_entries))
			return -1;
		*p++ = sg_page_iter_page(&page_iter);
	}
	return 0;
}
	if (addrs) {
EXPORT_SYMBOL(drm_prime_sg_to_page_array);

/**
 * drm_prime_sg_to_dma_addr_array - convert an sg table into a dma addr array
 * @sgt: scatter-gather table to convert
 * @addrs: array to store the dma bus address of each page
 * @max_entries: size of both the passed-in arrays
 *
 * Exports an sg table into an array of addresses.
 *
 * Drivers should use this in their &drm_driver.gem_prime_import_sg_table
 * implementation.
 */
int drm_prime_sg_to_dma_addr_array(struct sg_table *sgt, dma_addr_t *addrs,
				   int max_entries)
{
	struct sg_dma_page_iter dma_iter;
	dma_addr_t *a = addrs;

	for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
		if (WARN_ON(a - addrs >= max_entries))
			return -1;
		*a++ = sg_page_iter_dma_address(&dma_iter);
	}
	}

	return 0;
}
EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
EXPORT_SYMBOL(drm_prime_sg_to_dma_addr_array);

/**
 * drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
+1 −2
Original line number Diff line number Diff line
@@ -135,8 +135,7 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
		goto fail;
	}

	ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages,
					       NULL, npages);
	ret = drm_prime_sg_to_page_array(sgt, etnaviv_obj->pages, npages);
	if (ret)
		goto fail;

+1 −1
Original line number Diff line number Diff line
@@ -260,7 +260,7 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
		return -ENOMEM;
	}

	drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages);
	drm_prime_sg_to_page_array(sgt, mtk_gem->pages, npages);

	mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
			       pgprot_writecombine(PAGE_KERNEL));
+1 −1
Original line number Diff line number Diff line
@@ -1180,7 +1180,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
		goto fail;
	}

	ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);
	ret = drm_prime_sg_to_page_array(sgt, msm_obj->pages, npages);
	if (ret) {
		mutex_unlock(&msm_obj->lock);
		goto fail;
Loading