All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tursulin@ursulin.net>
To: Intel-gfx@lists.freedesktop.org
Subject: [RFC 2/7] drm/i915: Use i915_sg_create for userptr
Date: Thu, 13 Oct 2016 10:03:59 +0100	[thread overview]
Message-ID: <1476349444-7331-3-git-send-email-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <1476349444-7331-1-git-send-email-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@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.ursulin@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

  parent reply	other threads:[~2016-10-13  9:04 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-13  9:03 [RFC 0/7] Save megabytes of wasted sg entries Tvrtko Ursulin
2016-10-13  9:03 ` [RFC 1/7] drm/i915: Extract sg creation into a helper Tvrtko Ursulin
2016-10-13  9:20   ` Chris Wilson
2016-10-13  9:55     ` Tvrtko Ursulin
2016-10-13 10:12       ` Chris Wilson
2016-10-13  9:03 ` Tvrtko Ursulin [this message]
2016-10-13  9:04 ` [RFC 3/7] drm/i915: Use i915_sg_create for partial views Tvrtko Ursulin
2016-10-13  9:04 ` [RFC 4/7] drm/i915: Use i915_sg_create for rotated pages view Tvrtko Ursulin
2016-10-13  9:04 ` [RFC 5/7] drm/i915: Use i915_sg_create for dmabuf Tvrtko Ursulin
2016-10-13  9:15   ` Chris Wilson
2016-10-13  9:49     ` Tvrtko Ursulin
2016-10-13  9:04 ` [RFC 6/7] lib/scatterlist: Add sg_trim_table Tvrtko Ursulin
2016-10-13  9:23   ` Chris Wilson
2016-10-13  9:51     ` Tvrtko Ursulin
2016-10-13  9:04 ` [RFC 7/7] drm/i915: Trim sg table after creating it Tvrtko Ursulin
2016-10-13 10:27 ` ✗ Fi.CI.BAT: failure for Save megabytes of wasted sg entries Patchwork
2016-10-13 11:24   ` Saarinen, Jani
2016-10-13 15:33     ` Daniel Vetter
2016-10-13 16:09       ` Tvrtko Ursulin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1476349444-7331-3-git-send-email-tvrtko.ursulin@linux.intel.com \
    --to=tursulin@ursulin.net \
    --cc=Intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.