On 07/10/2016 10:46, Chris Wilson wrote: > 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 > --- > 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); Reviewed-by: John Harrison