<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    On 07/10/2016 10:46, Chris Wilson wrote:<br>
    <blockquote
      cite="mid:20161007094635.28319-16-chris@chris-wilson.co.uk"
      type="cite">
      <pre wrap="">We can use the radixtree index of the obj->pages to find the start
position of the desired partial range.

Signed-off-by: Chris Wilson <a class="moz-txt-link-rfc2396E" href="mailto:chris@chris-wilson.co.uk"><chris@chris-wilson.co.uk></a>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 38 +++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 78b692e5b998..7e0c98576e72 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3562,35 +3562,45 @@ intel_partial_pages(const struct i915_ggtt_view *view,
                    struct drm_i915_gem_object *obj)
 {
        struct sg_table *st;
-       struct scatterlist *sg;
-       struct sg_page_iter obj_sg_iter;
+       struct scatterlist *sg, *iter;
+       unsigned int count = view->params.partial.size;
+       unsigned int offset;
        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);
+       ret = sg_alloc_table(st, count, GFP_KERNEL);
        if (ret)
                goto err_sg_alloc;
 
+       iter = i915_gem_object_get_sg(obj,
+                                     view->params.partial.offset,
+                                     &offset);
+
        sg = st->sgl;
        st->nents = 0;
-       for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
-               view->params.partial.offset)
-       {
-               if (st->nents >= view->params.partial.size)
-                       break;
+       do {
+               unsigned int len =
+                       min(iter->length, (count - offset) << PAGE_SHIFT);
 
-               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_set_page(sg, NULL, len, 0);
+               sg_dma_address(sg) =
+                       sg_dma_address(iter) + (offset << PAGE_SHIFT);
+               sg_dma_len(sg) = len;
 
-               sg = sg_next(sg);
                st->nents++;
-       }
+               count -= len >> PAGE_SHIFT;
+               if (count == 0) {
+                       sg_mark_end(sg);
+                       return st;
+               }
 
-       return st;
+               sg = __sg_next(sg);
+               iter = __sg_next(iter);
+               offset = 0;
+       } while (1);
 
 err_sg_alloc:
        kfree(st);
</pre>
    </blockquote>
    <br>
    <br>
    Reviewed-by: John Harrison <a class="moz-txt-link-rfc2396E"
      href="mailto:john.c.harrison@intel.com"><john.c.harrison@intel.com></a><br>
    <br>
  </body>
</html>