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: Christian König <christian.koenig@amd.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/403838/
This commit is contained in:
parent
18f7608a67
commit
c67e62790f
|
@ -918,8 +918,8 @@ 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,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1264,9 +1264,8 @@ 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,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
for_each_sgtable_page(sgt, &page_iter, 0) {
|
||||
if (WARN_ON(p - pages >= max_entries))
|
||||
return -1;
|
||||
*p++ = sg_page_iter_page(&page_iter);
|
||||
}
|
||||
if (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_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_dma_addr_array);
|
||||
|
||||
/**
|
||||
* drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1235,9 +1235,8 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
|
|||
return 0;
|
||||
|
||||
if (slave && ttm->sg) {
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, NULL,
|
||||
ttm_dma->dma_address,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, ttm_dma->dma_address,
|
||||
ttm->num_pages);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1324,8 +1324,7 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size,
|
|||
}
|
||||
|
||||
omap_obj->pages = pages;
|
||||
ret = drm_prime_sg_to_page_addr_arrays(sgt, pages, NULL,
|
||||
npages);
|
||||
ret = drm_prime_sg_to_page_array(sgt, pages, npages);
|
||||
if (ret) {
|
||||
omap_gem_free_object(obj);
|
||||
obj = ERR_PTR(-ENOMEM);
|
||||
|
|
|
@ -395,8 +395,8 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, struct ttm_tt *
|
|||
if (r)
|
||||
goto release_sg;
|
||||
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, NULL, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -574,9 +574,8 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev,
|
|||
}
|
||||
|
||||
if (slave && ttm->sg) {
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, NULL,
|
||||
gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -356,8 +356,7 @@ static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev,
|
|||
}
|
||||
|
||||
obj->pages_pin_count++; /* perma-pinned */
|
||||
drm_prime_sg_to_page_addr_arrays(obj->table, obj->pages, NULL,
|
||||
npages);
|
||||
drm_prime_sg_to_page_array(obj->table, obj->pages, npages);
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,8 +220,8 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev,
|
|||
|
||||
xen_obj->sgt_imported = sgt;
|
||||
|
||||
ret = drm_prime_sg_to_page_addr_arrays(sgt, xen_obj->pages,
|
||||
NULL, xen_obj->num_pages);
|
||||
ret = drm_prime_sg_to_page_array(sgt, xen_obj->pages,
|
||||
xen_obj->num_pages);
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
|
|
@ -105,8 +105,9 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
|||
|
||||
void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
|
||||
|
||||
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
||||
dma_addr_t *addrs, int max_pages);
|
||||
|
||||
int drm_prime_sg_to_page_array(struct sg_table *sgt, struct page **pages,
|
||||
int max_pages);
|
||||
int drm_prime_sg_to_dma_addr_array(struct sg_table *sgt, dma_addr_t *addrs,
|
||||
int max_pages);
|
||||
|
||||
#endif /* __DRM_PRIME_H__ */
|
||||
|
|
Loading…
Reference in New Issue