[Intel-gfx] [PATCH] drm/i915: Move VMAs to inactive as request are retired
Daniel Vetter
daniel at ffwll.ch
Thu Nov 26 06:41:16 PST 2015
On Thu, Nov 26, 2015 at 02:07:57PM +0000, Tvrtko Ursulin wrote:
>
> On 26/11/15 10:01, Daniel Vetter wrote:
> >On Wed, Nov 25, 2015 at 10:16:37AM +0000, Tvrtko Ursulin wrote:
> >>
> >>On 24/11/15 17:47, Daniel Vetter wrote:
> >>>On Mon, Nov 23, 2015 at 03:12:35PM +0000, Tvrtko Ursulin wrote:
> >>>>From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> >>>>
> >>>>Current code moves _any_ VMA to the inactive list only when
> >>>>_all_ rendering on an object (so from any context or VM) has
> >>>>been completed.
> >>>>
> >>>>This creates an un-natural situation where the context (and
> >>>>VM) destructors can run with VMAs still on the respective
> >>>>active list.
> >>>>
> >>>>Change here is to move VMAs to the inactive list as the
> >>>>requests are getting retired.
> >>>>
> >>>>Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> >>>>Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92638
> >>>>Testcase: igt/gem_request_retire/retire-vma-not-inactive
> >>>>Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> >>>>Cc: Chris Wilson <chris at chris-wilson.co.uk>
> >>>>---
> >>>> drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++-
> >>>> 1 file changed, 16 insertions(+), 1 deletion(-)
> >>>>
> >>>>diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> >>>>index cd7e102720f4..47a743246d2c 100644
> >>>>--- a/drivers/gpu/drm/i915/i915_gem.c
> >>>>+++ b/drivers/gpu/drm/i915/i915_gem.c
> >>>>@@ -2413,17 +2413,32 @@ static void
> >>>> i915_gem_object_retire__read(struct drm_i915_gem_object *obj, int ring)
> >>>> {
> >>>> struct i915_vma *vma;
> >>>>+ struct i915_address_space *vm;
> >>>>
> >>>> RQ_BUG_ON(obj->last_read_req[ring] == NULL);
> >>>> RQ_BUG_ON(!(obj->active & (1 << ring)));
> >>>>
> >>>> list_del_init(&obj->ring_list[ring]);
> >>>>- i915_gem_request_assign(&obj->last_read_req[ring], NULL);
> >>>>
> >>>> if (obj->last_write_req && obj->last_write_req->ring->id == ring)
> >>>> i915_gem_object_retire__write(obj);
> >>>>
> >>>> obj->active &= ~(1 << ring);
> >>>>+
> >>>>+ if (obj->last_read_req[ring]->ctx->ppgtt)
> >>>>+ vm = &obj->last_read_req[ring]->ctx->ppgtt->base;
> >>>>+ else
> >>>>+ vm = &obj->last_read_req[ring]->i915->gtt.base;
> >>>>+
> >>>>+ list_for_each_entry(vma, &obj->vma_list, vma_link) {
> >>>>+ if (vma->vm == vm &&
> >>>>+ vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL &&
> >>>>+ !list_empty(&vma->mm_list))
> >>>>+ list_move_tail(&vma->mm_list, &vma->vm->inactive_list);
> >>>>+ }
> >>>
> >>>This is only a partial solution since with schedulers and semaphores and a
> >>>few depencies on a given object, but in different vm you can still end up
> >>>with an object that is idle in a vm, but slipped through here.
> >>
> >>Could you describe the exact scenario you had in mind? I won't pretend it
> >>this is simple code and I have it all figured out.
> >
> >Well tbh I don't fully understand what exactly your code will do in all
> >corner-cases since there's a lot of ifs and special cases. But
> >fundamentally the problem is that an object can be active in a given vm
> >and there's no request pointing at the corresponding context in either
> >last_read_req or last_write_req. It works like this:
> >
> >- ctx A uses obj 1
> >- ctx B uses obj 1 on the same engine
> >
> >Your code above will miss to retire obj 1 on ctx 1's vm, so if you then
> >destroy ctx A you'll hit the nice warn above (presuming ctx B keeps obj 1
> >busy for all that time). So not even scheduler needed.
>
> Ah yes... I was even close to figuring this one out but got too confused and
> decided I am imagining things...
>
> >Fundamentally if you really want to accurately keep track of vma instaed
> >of obj activeness, then you need to have per-vma tracking of all of it,
> >i.e. all the last_*_req stuff.
> >
> >Without that we essentially only keep track of an lru on each vm, and the
> >active/inactive split is totally bogus (well not quite, but since it
> >reflects obj->active there's not really any value, but it does create tons
> >of confusion).
> >
> >To unconfuse this we'd need to have proper vma active tracking (not sure
> >whether that's worth it) or just merge the per-vm active/inactive lists
> >since they're really just one big list.
>
> ... so all in all best to drop this for now. Since it is a half solution,
> plus Chris says Synmark, if I read it right, likes to use an object from a
> zillion of contexts simultaneously so would be hurt by traversing the
> obj->vma_list here.
Yeah, walking obj->vma_list pretty much means unclean design.
Unfortunately we still have a pile of those left from the original ppgtt
enabling, and the fixes for those are burried in Chris' tree somewhere.
> >>>Also, checking for the view type is some strange layering. Why that?
> >>
> >>!ppgtt to skip potential other views I thought, no?
> >
> >The vma lrus should be irrespective of ggtt vs. ppgtt or exactly what kind
> >of view it is. If we exclude special case everywhere the might pop up but
> >should the code will become unreadable (and the abstraction useless). What
> >do you fear could blow up without this check?
>
> Nothing really, since other view types will never end up on the active list.
> Just a never ending dilemma of whether to be generic or optimal. :)
Well in this case there shouldn't be a dilemma: Since the view special
case can't happen and doesn't matter, being generic also means less code
and hence more optimal ;-)
Cheers, Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list