diff mbox

[RFC,3/7] drm/i915: Use i915_sg_create for partial views

Message ID 1476349444-7331-4-git-send-email-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tvrtko Ursulin Oct. 13, 2016, 9:04 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Simplify the partial view creation loop by using the newly
introduced helpers.

It also allows the list to be coalesced when possbile.

New i915_sg_add_dma helper was added to allow adding just
the DMA address entries to the list.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |  1 +
 drivers/gpu/drm/i915/i915_gem.c     | 38 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.c | 34 ++++++++-------------------------
 3 files changed, 47 insertions(+), 26 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e226794ffc1b..641a1dbc87b8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -4019,6 +4019,7 @@  struct i915_sg_create_state {
 
 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);
+void i915_sg_add_dma(struct i915_sg_create_state *state, dma_addr_t addr);
 struct sg_table *i915_sg_complete(struct i915_sg_create_state *state);
 void i915_sg_abort(struct i915_sg_create_state *state);
 
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1c1aa3bbde8a..05dc2af1a89e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2268,6 +2268,8 @@  struct i915_sg_create_state *i915_sg_create(unsigned int page_count)
  * 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.
+ *
+ * MUST NOT be mixed with i915_sg_add_dma!
  */
 void i915_sg_add_page(struct i915_sg_create_state *state, struct page *page)
 {
@@ -2291,6 +2293,42 @@  void i915_sg_add_page(struct i915_sg_create_state *state, struct page *page)
 }
 
 /**
+ * i915_sg_add_dma - adds a dma address to the sg list being built
+ * @state: state created with i915_sg_create
+ * @addr: dma address to add
+ *
+ * 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.
+ *
+ * MUST NOT be mixed with i915_sg_add_page!
+ */
+void i915_sg_add_dma(struct i915_sg_create_state *state, dma_addr_t addr)
+{
+	struct scatterlist *sg = state->sg;
+
+	if (!state->idx ||
+	    sg->length >= state->max_segment ||
+	    addr != state->last_pfn + PAGE_SIZE) {
+		if (state->idx)
+			sg = sg_next(sg);
+		state->st->nents++;
+		sg_set_page(sg, NULL, PAGE_SIZE, 0);
+		sg_dma_address(sg) = addr;
+		sg_dma_len(sg) = PAGE_SIZE;
+	} else {
+		sg->length += PAGE_SIZE;
+		if (IS_ENABLED(CONFIG_NEED_SG_DMA_LENGTH))
+			sg_dma_len(sg) += PAGE_SIZE;
+	}
+
+	state->last_pfn = addr;
+	state->sg = sg;
+	state->idx++;
+}
+
+/**
  * i915_sg_complete - completes the sg list building
  * @state: state created with i915_sg_create
  *
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 2d846aa39ca5..f0c70e7c8daa 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3559,41 +3559,23 @@  static struct sg_table *
 intel_partial_pages(const struct i915_ggtt_view *view,
 		    struct drm_i915_gem_object *obj)
 {
-	struct sg_table *st;
-	struct scatterlist *sg;
+	struct i915_sg_create_state *state;
 	struct sg_page_iter obj_sg_iter;
-	int ret = -ENOMEM;
 
-	st = kmalloc(sizeof(*st), GFP_KERNEL);
-	if (!st)
-		goto err_st_alloc;
-
-	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
-	if (ret)
-		goto err_sg_alloc;
+	state = i915_sg_create(view->params.partial.size);
+	if (IS_ERR(state))
+		return ERR_CAST(state);
 
-	sg = st->sgl;
-	st->nents = 0;
 	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
-		view->params.partial.offset)
+			 view->params.partial.offset)
 	{
-		if (st->nents >= view->params.partial.size)
+		if (state->idx >= view->params.partial.size)
 			break;
 
-		sg_set_page(sg, NULL, PAGE_SIZE, 0);
-		sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
-		sg_dma_len(sg) = PAGE_SIZE;
-
-		sg = sg_next(sg);
-		st->nents++;
+		i915_sg_add_dma(state, sg_page_iter_dma_address(&obj_sg_iter));
 	}
 
-	return st;
-
-err_sg_alloc:
-	kfree(st);
-err_st_alloc:
-	return ERR_PTR(ret);
+	return i915_sg_complete(state);
 }
 
 static int