[Intel-gfx] [PATCH] drm/i915: Mark the final obj->pages sg entry as last

Chris Wilson chris at chris-wilson.co.uk
Tue Jun 9 02:53:23 PDT 2015


On Tue, Jun 09, 2015 at 12:46:30PM +0300, Imre Deak wrote:
> On ti, 2015-06-09 at 10:19 +0100, Chris Wilson wrote:
> > Currently we may mark the subsequent sg entry as the last, instead of
> > the actual last element we used. If a later iterator only used
> > sg_is_last() (such as sg_next()) then we may access the NULL page stored
> > in the elements beyond the contracted table. This may explain the
> > occasional NULL dereference we see in insert pages, such as
> > https://bugzilla.redhat.com/show_bug.cgi?id=1227892
> > 
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Imre Deak <imre.deak at intel.com>
> > Cc: stable at vger.kernel.org
> > ---
> >  drivers/gpu/drm/i915/i915_gem.c | 10 +++++-----
> >  1 file changed, 5 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index be35f0486202..f3b66461dc68 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -2195,7 +2195,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
> >  	int page_count, i;
> >  	struct address_space *mapping;
> >  	struct sg_table *st;
> > -	struct scatterlist *sg;
> > +	struct scatterlist *sg, *end;
> >  	struct sg_page_iter sg_iter;
> >  	struct page *page;
> >  	unsigned long last_pfn = 0;	/* suppress gcc warning */
> > @@ -2227,7 +2227,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
> >  	gfp = mapping_gfp_mask(mapping);
> >  	gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
> >  	gfp &= ~(__GFP_IO | __GFP_WAIT);
> > -	sg = st->sgl;
> > +	end = sg = st->sgl;
> >  	st->nents = 0;
> >  	for (i = 0; i < page_count; i++) {
> >  		page = shmem_read_mapping_page_gfp(mapping, i, gfp);
> > @@ -2253,13 +2253,13 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
> >  		if (swiotlb_nr_tbl()) {
> >  			st->nents++;
> >  			sg_set_page(sg, page, PAGE_SIZE, 0);
> > -			sg = sg_next(sg);
> > +			sg = sg_next(end = sg);
> 
> This would make sense, but for swiotlb_nr_tbl() we don't mark the last
> element, it's done by sg_alloc_table().

sg_alloc_table() uses sg_mark_end(&sgl[st->orig_nents-1]);
Hmm, we don't do page compression for swiotlb? Ok, then this part is
redundant.

> 
> >  			continue;
> >  		}
> >  #endif
> >  		if (!i || page_to_pfn(page) != last_pfn + 1) {
> >  			if (i)
> > -				sg = sg_next(sg);
> > +				sg = sg_next(end = sg);
> 
> But this looks incorrect to me, sg points now to the last element for
> which we set the page below and end points to one before the last. Or
> I'm (still) missing something..

Nah, this was a change I made to try and reduce te patch size.
Originally I did sg_set_page(); end = sg; but then thought I could avoid
resetting end to the same sg in a few cases.
Thanks,
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


More information about the Intel-gfx mailing list