Message ID | 20180423180854.24219-3-chris@chris-wilson.co.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 23/04/2018 19:08, Chris Wilson wrote: > We don't need to track every ring for its lifetime as they are managed > by the contexts/engines. What we do want to track are the live rings so > that we can sporadically clean up requests if userspace falls behind. We > can simply restrict the gt->rings list to being only gt->live_rings. > > v2: s/live/active/ for consistency with gt.active_requests > > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> > --- > drivers/gpu/drm/i915/i915_drv.h | 3 ++- > drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- > drivers/gpu/drm/i915/i915_request.c | 10 ++++++++-- > drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ---- > drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- > drivers/gpu/drm/i915/selftests/mock_engine.c | 4 ---- > drivers/gpu/drm/i915/selftests/mock_gem_device.c | 5 +++-- > 7 files changed, 18 insertions(+), 16 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 1837c01d44d0..54351cace362 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2060,7 +2060,8 @@ struct drm_i915_private { > > struct i915_gem_timeline global_timeline; > struct list_head timelines; > - struct list_head rings; > + > + struct list_head active_rings; > u32 active_requests; > u32 request_serial; > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index 906e2395c245..56c79df5ebce 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -141,6 +141,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915) > { > lockdep_assert_held(&i915->drm.struct_mutex); > GEM_BUG_ON(i915->gt.active_requests); > + GEM_BUG_ON(!list_empty(&i915->gt.active_rings)); > > if (!i915->gt.awake) > return I915_EPOCH_INVALID; > @@ -5599,9 +5600,10 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv) > if (!dev_priv->priorities) > goto err_dependencies; > > - mutex_lock(&dev_priv->drm.struct_mutex); > - INIT_LIST_HEAD(&dev_priv->gt.rings); > INIT_LIST_HEAD(&dev_priv->gt.timelines); > + INIT_LIST_HEAD(&dev_priv->gt.active_rings); > + > + mutex_lock(&dev_priv->drm.struct_mutex); > err = i915_gem_timeline_init__global(dev_priv); > mutex_unlock(&dev_priv->drm.struct_mutex); > if (err) > diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c > index 0a117bf9e455..f13b7a1a0aa9 100644 > --- a/drivers/gpu/drm/i915/i915_request.c > +++ b/drivers/gpu/drm/i915/i915_request.c > @@ -321,6 +321,7 @@ static void advance_ring(struct i915_request *request) > * noops - they are safe to be replayed on a reset. > */ > tail = READ_ONCE(request->tail); > + list_del(&ring->active_link); > } else { > tail = request->postfix; > } > @@ -1081,6 +1082,8 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) > i915_gem_active_set(&timeline->last_request, request); > > list_add_tail(&request->ring_link, &ring->request_list); > + if (list_is_first(&request->ring_link, &ring->request_list)) > + list_add(&ring->active_link, &request->i915->gt.active_rings); So sneaky.. lets see if it is justified in its new home. :) > request->emitted_jiffies = jiffies; > > /* > @@ -1403,14 +1406,17 @@ static void ring_retire_requests(struct intel_ring *ring) > > void i915_retire_requests(struct drm_i915_private *i915) > { > - struct intel_ring *ring, *next; > + struct intel_ring *ring, *tmp; > > lockdep_assert_held(&i915->drm.struct_mutex); > > if (!i915->gt.active_requests) > return; > > - list_for_each_entry_safe(ring, next, &i915->gt.rings, link) > + /* An outstanding request must be on a still active ring somewhere */ > + GEM_BUG_ON(list_empty(&i915->gt.active_rings)); Okay, but I still think my assert would be stronger. As long as we allow calling this function with no active requests, why not check both internal states are consistent every time? > + > + list_for_each_entry_safe(ring, tmp, &i915->gt.active_rings, active_link) > ring_retire_requests(ring); > } > > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c > index 75dca28782ee..3d02b2c779e7 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.c > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c > @@ -1149,8 +1149,6 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) > } > ring->vma = vma; > > - list_add(&ring->link, &engine->i915->gt.rings); > - > return ring; > } > > @@ -1162,8 +1160,6 @@ intel_ring_free(struct intel_ring *ring) > i915_vma_close(ring->vma); > __i915_gem_object_release_unless_active(obj); > > - list_del(&ring->link); > - > kfree(ring); > } > > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h > index d816f8dea245..e8d17bcd9bee 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > @@ -129,7 +129,7 @@ struct intel_ring { > void *vaddr; > > struct list_head request_list; > - struct list_head link; > + struct list_head active_link; > > u32 head; > u32 tail; > diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c > index a0bc324edadd..74a88913623f 100644 > --- a/drivers/gpu/drm/i915/selftests/mock_engine.c > +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c > @@ -140,15 +140,11 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine) > INIT_LIST_HEAD(&ring->request_list); > intel_ring_update_space(ring); > > - list_add(&ring->link, &engine->i915->gt.rings); > - > return ring; > } > > static void mock_ring_free(struct intel_ring *ring) > { > - list_del(&ring->link); > - > kfree(ring); > } > > diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > index ac4bacf8b5b9..f22a2b35a283 100644 > --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c > +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c > @@ -224,9 +224,10 @@ struct drm_i915_private *mock_gem_device(void) > if (!i915->priorities) > goto err_dependencies; > > - mutex_lock(&i915->drm.struct_mutex); > - INIT_LIST_HEAD(&i915->gt.rings); > INIT_LIST_HEAD(&i915->gt.timelines); > + INIT_LIST_HEAD(&i915->gt.active_rings); > + > + mutex_lock(&i915->drm.struct_mutex); > err = i915_gem_timeline_init__global(i915); > if (err) { > mutex_unlock(&i915->drm.struct_mutex); > Regards, Tvrtko
Quoting Tvrtko Ursulin (2018-04-24 10:37:03) > > On 23/04/2018 19:08, Chris Wilson wrote: > > @@ -1403,14 +1406,17 @@ static void ring_retire_requests(struct intel_ring *ring) > > > > void i915_retire_requests(struct drm_i915_private *i915) > > { > > - struct intel_ring *ring, *next; > > + struct intel_ring *ring, *tmp; > > > > lockdep_assert_held(&i915->drm.struct_mutex); > > > > if (!i915->gt.active_requests) > > return; > > > > - list_for_each_entry_safe(ring, next, &i915->gt.rings, link) > > + /* An outstanding request must be on a still active ring somewhere */ > > + GEM_BUG_ON(list_empty(&i915->gt.active_rings)); > > Okay, but I still think my assert would be stronger. As long as we allow > calling this function with no active requests, why not check both > internal states are consistent every time? I agree that checking both simultaneously would be useful, but we do check both for cross-consistency already, just not in the same place. It's just doing so in a readable fashion. After this we aren't using active_requests as more than a boolean; so I'm wondering if not just replacing it with list_empty(&active_rings) for the infrequent uses. -Chris
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1837c01d44d0..54351cace362 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2060,7 +2060,8 @@ struct drm_i915_private { struct i915_gem_timeline global_timeline; struct list_head timelines; - struct list_head rings; + + struct list_head active_rings; u32 active_requests; u32 request_serial; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 906e2395c245..56c79df5ebce 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -141,6 +141,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915) { lockdep_assert_held(&i915->drm.struct_mutex); GEM_BUG_ON(i915->gt.active_requests); + GEM_BUG_ON(!list_empty(&i915->gt.active_rings)); if (!i915->gt.awake) return I915_EPOCH_INVALID; @@ -5599,9 +5600,10 @@ int i915_gem_init_early(struct drm_i915_private *dev_priv) if (!dev_priv->priorities) goto err_dependencies; - mutex_lock(&dev_priv->drm.struct_mutex); - INIT_LIST_HEAD(&dev_priv->gt.rings); INIT_LIST_HEAD(&dev_priv->gt.timelines); + INIT_LIST_HEAD(&dev_priv->gt.active_rings); + + mutex_lock(&dev_priv->drm.struct_mutex); err = i915_gem_timeline_init__global(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); if (err) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 0a117bf9e455..f13b7a1a0aa9 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -321,6 +321,7 @@ static void advance_ring(struct i915_request *request) * noops - they are safe to be replayed on a reset. */ tail = READ_ONCE(request->tail); + list_del(&ring->active_link); } else { tail = request->postfix; } @@ -1081,6 +1082,8 @@ void __i915_request_add(struct i915_request *request, bool flush_caches) i915_gem_active_set(&timeline->last_request, request); list_add_tail(&request->ring_link, &ring->request_list); + if (list_is_first(&request->ring_link, &ring->request_list)) + list_add(&ring->active_link, &request->i915->gt.active_rings); request->emitted_jiffies = jiffies; /* @@ -1403,14 +1406,17 @@ static void ring_retire_requests(struct intel_ring *ring) void i915_retire_requests(struct drm_i915_private *i915) { - struct intel_ring *ring, *next; + struct intel_ring *ring, *tmp; lockdep_assert_held(&i915->drm.struct_mutex); if (!i915->gt.active_requests) return; - list_for_each_entry_safe(ring, next, &i915->gt.rings, link) + /* An outstanding request must be on a still active ring somewhere */ + GEM_BUG_ON(list_empty(&i915->gt.active_rings)); + + list_for_each_entry_safe(ring, tmp, &i915->gt.active_rings, active_link) ring_retire_requests(ring); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 75dca28782ee..3d02b2c779e7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1149,8 +1149,6 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) } ring->vma = vma; - list_add(&ring->link, &engine->i915->gt.rings); - return ring; } @@ -1162,8 +1160,6 @@ intel_ring_free(struct intel_ring *ring) i915_vma_close(ring->vma); __i915_gem_object_release_unless_active(obj); - list_del(&ring->link); - kfree(ring); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index d816f8dea245..e8d17bcd9bee 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -129,7 +129,7 @@ struct intel_ring { void *vaddr; struct list_head request_list; - struct list_head link; + struct list_head active_link; u32 head; u32 tail; diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c index a0bc324edadd..74a88913623f 100644 --- a/drivers/gpu/drm/i915/selftests/mock_engine.c +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c @@ -140,15 +140,11 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine) INIT_LIST_HEAD(&ring->request_list); intel_ring_update_space(ring); - list_add(&ring->link, &engine->i915->gt.rings); - return ring; } static void mock_ring_free(struct intel_ring *ring) { - list_del(&ring->link); - kfree(ring); } diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index ac4bacf8b5b9..f22a2b35a283 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -224,9 +224,10 @@ struct drm_i915_private *mock_gem_device(void) if (!i915->priorities) goto err_dependencies; - mutex_lock(&i915->drm.struct_mutex); - INIT_LIST_HEAD(&i915->gt.rings); INIT_LIST_HEAD(&i915->gt.timelines); + INIT_LIST_HEAD(&i915->gt.active_rings); + + mutex_lock(&i915->drm.struct_mutex); err = i915_gem_timeline_init__global(i915); if (err) { mutex_unlock(&i915->drm.struct_mutex);
We don't need to track every ring for its lifetime as they are managed by the contexts/engines. What we do want to track are the live rings so that we can sporadically clean up requests if userspace falls behind. We can simply restrict the gt->rings list to being only gt->live_rings. v2: s/live/active/ for consistency with gt.active_requests Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- drivers/gpu/drm/i915/i915_request.c | 10 ++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ---- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- drivers/gpu/drm/i915/selftests/mock_engine.c | 4 ---- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 5 +++-- 7 files changed, 18 insertions(+), 16 deletions(-)