From: Tvrtko Ursulin <tvrtko.ursu...@intel.com>

Now that we have a helper which builds the sg lists, use it
from the userptr code as well.

To do this we first export the API and add kerneldoc for it.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursu...@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         | 33 +++++++++++++++++
 drivers/gpu/drm/i915/i915_gem.c         | 65 +++++++++++++++++++++++----------
 drivers/gpu/drm/i915/i915_gem_userptr.c | 51 +++++---------------------
 3 files changed, 87 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bf397b643cc0..e226794ffc1b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3999,4 +3999,37 @@ int remap_io_mapping(struct vm_area_struct *vma,
        __T;                                                            \
 })
 
+/**
+ * struct i915_sg_create_state - state object for the sg creation helpers
+ * @st: sg_table being created
+ * @sg: Current scatterlist entry iterated over
+ * @idx: Current page index iterated over
+ * @page_count: Number of pages requested for the sg table to hold at creation
+ * @max_segment: Maximum size in bytes of a single sg entry
+ * @last_pfn: Page frame number of the previously added page
+ */
+struct i915_sg_create_state {
+       struct sg_table *st;
+       struct scatterlist *sg;
+       unsigned int idx;
+       unsigned int page_count;
+       unsigned long max_segment;
+       unsigned long last_pfn;
+};
+
+struct i915_sg_create_state *i915_sg_create(unsigned int page_count);
+void i915_sg_add_page(struct i915_sg_create_state *state, struct page *page);
+struct sg_table *i915_sg_complete(struct i915_sg_create_state *state);
+void i915_sg_abort(struct i915_sg_create_state *state);
+
+/**
+ * i915_sg_for_each_page - sg creation iterator
+ * @state: state object created by i915_sg_create
+ *
+ * Iterates page_count times over the created state allowing the caller to
+ * call i915_sg_add_page for all the pages it wants to build the list from.
+ */
+#define i915_sg_for_each_page(state) \
+       for( ; (state)->idx < (state)->page_count; )
+
 #endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 93b047735e6b..1c1aa3bbde8a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2216,17 +2216,16 @@ static unsigned long swiotlb_max_size(void)
 #endif
 }
 
-struct i915_sg_create_state {
-       struct sg_table *st;
-       struct scatterlist *sg;
-       unsigned int idx;
-       unsigned int page_count;
-       unsigned long max_segment;
-       unsigned long last_pfn;
-};
-
-static struct i915_sg_create_state *
-i915_sg_create(unsigned int page_count)
+/**
+ * i915_sg_create - creates the state object for sg list building
+ * @page_count: number of pages the caller intends to add to the list
+ *
+ * This function creates a state object which is to be used with the
+ * accompanying family of functions used to build the scatter-gather list.
+ *
+ * Returns a pointer to the state structure or ERR_PTR otherwise.
+ */
+struct i915_sg_create_state *i915_sg_create(unsigned int page_count)
 {
        struct i915_sg_create_state *state;
        struct sg_table *st;
@@ -2260,8 +2259,17 @@ i915_sg_create(unsigned int page_count)
        return state;
 }
 
-static void
-i915_sg_add_page(struct i915_sg_create_state *state, struct page *page)
+/**
+ * i915_sg_add_page - adds a page to the sg list being built
+ * @state: state created with i915_sg_create
+ * @page: struct page pointer of the page to add to the list
+ *
+ * Intended to be called under the i915_sg_for_each_page iterator once for each
+ * page which needs to be added to the sg list.
+ * Function manages the internal state which can be read (only!) by the caller
+ * where appropriate.
+ */
+void i915_sg_add_page(struct i915_sg_create_state *state, struct page *page)
 {
        unsigned long pfn = page_to_pfn(page);
        struct scatterlist *sg = state->sg;
@@ -2282,8 +2290,17 @@ i915_sg_add_page(struct i915_sg_create_state *state, 
struct page *page)
        state->idx++;
 }
 
-static struct sg_table *
-i915_sg_complete(struct i915_sg_create_state *state)
+/**
+ * i915_sg_complete - completes the sg list building
+ * @state: state created with i915_sg_create
+ *
+ * When all the pages have been successsfuly added to the sg list, this 
function
+ * is called to retrieve the fully build sg_table pointer.
+ * State object is not valid after this is called.
+ *
+ * Returns the sg_table pointer ready to be used.
+ */
+struct sg_table *i915_sg_complete(struct i915_sg_create_state *state)
 {
        struct sg_table *st = state->st;
 
@@ -2295,17 +2312,25 @@ i915_sg_complete(struct i915_sg_create_state *state)
        return st;
 }
 
-static void
-i915_sg_abort(struct i915_sg_create_state *state)
+/**
+ * i915_sg_abort - aborts the sg list building
+ * @state: state previously created with i915_sg_create
+ *
+ * In cases when something goes wrong with the sg list building, callers need
+ * to call this function to cleanup the objects and state allocated by the
+ * i915_sg_create.
+ * State object must not be accessed after calling this.
+ * Callers are responsible to do the correct thing with regards to individual
+ * page freeing/releasing themselves, but this helper will free the sg table
+ * and scatter gather entries.
+ */
+void i915_sg_abort(struct i915_sg_create_state *state)
 {
        sg_free_table(state->st);
        kfree(state->st);
        kfree(state);
 }
 
-#define i915_sg_for_each_page(state) \
-       for( ; (state)->idx < (state)->page_count; )
-
 static int
 i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c 
b/drivers/gpu/drm/i915/i915_gem_userptr.c
index e537930c64b5..ced19610d911 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -397,54 +397,21 @@ struct get_pages_work {
        struct task_struct *task;
 };
 
-#if IS_ENABLED(CONFIG_SWIOTLB)
-#define swiotlb_active() swiotlb_nr_tbl()
-#else
-#define swiotlb_active() 0
-#endif
-
-static int
-st_set_pages(struct sg_table **st, struct page **pvec, int num_pages)
-{
-       struct scatterlist *sg;
-       int ret, n;
-
-       *st = kmalloc(sizeof(**st), GFP_KERNEL);
-       if (*st == NULL)
-               return -ENOMEM;
-
-       if (swiotlb_active()) {
-               ret = sg_alloc_table(*st, num_pages, GFP_KERNEL);
-               if (ret)
-                       goto err;
-
-               for_each_sg((*st)->sgl, sg, num_pages, n)
-                       sg_set_page(sg, pvec[n], PAGE_SIZE, 0);
-       } else {
-               ret = sg_alloc_table_from_pages(*st, pvec, num_pages,
-                                               0, num_pages << PAGE_SHIFT,
-                                               GFP_KERNEL);
-               if (ret)
-                       goto err;
-       }
-
-       return 0;
-
-err:
-       kfree(*st);
-       *st = NULL;
-       return ret;
-}
-
 static int
 __i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj,
                             struct page **pvec, int num_pages)
 {
+       struct i915_sg_create_state *state;
        int ret;
 
-       ret = st_set_pages(&obj->pages, pvec, num_pages);
-       if (ret)
-               return ret;
+       state = i915_sg_create(num_pages);
+       if (IS_ERR(state))
+               return PTR_ERR(state);
+
+       i915_sg_for_each_page(state)
+               i915_sg_add_page(state, pvec[state->idx]);
+
+       obj->pages = i915_sg_complete(state);
 
        ret = i915_gem_gtt_prepare_object(obj);
        if (ret) {
-- 
2.7.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to