drm/i915: Be defensive when cleaning up i915_gem_internal pages
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 31 Jan 2017 10:46:30 +0000 (10:46 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 31 Jan 2017 11:15:03 +0000 (11:15 +0000)
If we abort the i915_gem_internal get_pages, we mark the failing sg as
the last. However, that means we iterate upto and including the failing
sg element and results in us trying to free the unallocated sg_page().

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170131104630.3074-1-chris@chris-wilson.co.uk
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
drivers/gpu/drm/i915/i915_gem_internal.c

index 17ce53d0d092fbeb60a8a52d7839887613490de2..64d8fb3fd76441e7c85ece8a9e096667e43ca635 100644 (file)
@@ -35,8 +35,10 @@ static void internal_free_pages(struct sg_table *st)
 {
        struct scatterlist *sg;
 
-       for (sg = st->sgl; sg; sg = __sg_next(sg))
-               __free_pages(sg_page(sg), get_order(sg->length));
+       for (sg = st->sgl; sg; sg = __sg_next(sg)) {
+               if (sg_page(sg))
+                       __free_pages(sg_page(sg), get_order(sg->length));
+       }
 
        sg_free_table(st);
        kfree(st);
@@ -116,6 +118,7 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
        return st;
 
 err:
+       sg_set_page(sg, NULL, 0, 0);
        sg_mark_end(sg);
        internal_free_pages(st);
        return ERR_PTR(-ENOMEM);