drm/prime: introduce sg->pages/addr arrays helper
authorDave Airlie <airlied@redhat.com>
Fri, 18 May 2012 14:40:33 +0000 (15:40 +0100)
committerDave Airlie <airlied@redhat.com>
Wed, 23 May 2012 09:45:57 +0000 (10:45 +0100)
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 <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_prime.c
include/drm/drmP.h

index 1bdf2b5..20dbf2c 100644 (file)
@@ -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)
 {
index 15d9179..31ad880 100644 (file)
@@ -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);