From 51ab7ba2673758561074184795bba5bac780a038 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 18 May 2012 15:40:33 +0100 Subject: [PATCH] drm/prime: introduce sg->pages/addr arrays helper the ttm drivers need this currently, in order to get fault handling working and efficient. It also allows addrs to be NULL for devices like udl. Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_prime.c | 36 ++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 1bdf2b54eaf6..20dbf2c45385 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -227,6 +227,42 @@ out: } EXPORT_SYMBOL(drm_prime_pages_to_sg); +/* export 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 */ +int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, + dma_addr_t *addrs, int max_pages) +{ + unsigned count; + struct scatterlist *sg; + struct page *page; + u32 len, offset; + int pg_index; + dma_addr_t addr; + + pg_index = 0; + for_each_sg(sgt->sgl, sg, sgt->nents, count) { + len = sg->length; + offset = sg->offset; + page = sg_page(sg); + addr = sg_dma_address(sg); + + while (len > 0) { + if (WARN_ON(pg_index >= max_pages)) + return -1; + pages[pg_index] = page; + if (addrs) + addrs[pg_index] = addr; + + page++; + addr += PAGE_SIZE; + len -= PAGE_SIZE; + pg_index++; + } + } + return 0; +} +EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays); /* helper function to cleanup a GEM/prime object */ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 15d91798dd31..31ad880ca2ef 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1558,6 +1558,8 @@ extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, + dma_addr_t *addrs, int max_pages); extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages); extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); -- 2.39.5