Commit cf4331dd authored by Chris Wilson's avatar Chris Wilson

drm/i915: Move find_active_request() to the engine

To find the active request, we need only search along the individual
engine for the right request. This does not require touching any global
GEM state, so move it into the engine compartment.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190305180332.30900-3-chris@chris-wilson.co.uk
parent fb251a72
...@@ -2996,9 +2996,6 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, ...@@ -2996,9 +2996,6 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old,
int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno); int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
struct i915_request *
i915_gem_find_active_request(struct intel_engine_cs *engine);
static inline bool __i915_wedged(struct i915_gpu_error *error) static inline bool __i915_wedged(struct i915_gpu_error *error)
{ {
return unlikely(test_bit(I915_WEDGED, &error->flags)); return unlikely(test_bit(I915_WEDGED, &error->flags));
......
...@@ -2803,51 +2803,6 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj, ...@@ -2803,51 +2803,6 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
return 0; return 0;
} }
static bool match_ring(struct i915_request *rq)
{
struct drm_i915_private *dev_priv = rq->i915;
u32 ring = I915_READ(RING_START(rq->engine->mmio_base));
return ring == i915_ggtt_offset(rq->ring->vma);
}
struct i915_request *
i915_gem_find_active_request(struct intel_engine_cs *engine)
{
struct i915_request *request, *active = NULL;
unsigned long flags;
/*
* We are called by the error capture, reset and to dump engine
* state at random points in time. In particular, note that neither is
* crucially ordered with an interrupt. After a hang, the GPU is dead
* and we assume that no more writes can happen (we waited long enough
* for all writes that were in transaction to be flushed) - adding an
* extra delay for a recent interrupt is pointless. Hence, we do
* not need an engine->irq_seqno_barrier() before the seqno reads.
* At all other times, we must assume the GPU is still running, but
* we only care about the snapshot of this moment.
*/
spin_lock_irqsave(&engine->timeline.lock, flags);
list_for_each_entry(request, &engine->timeline.requests, link) {
if (i915_request_completed(request))
continue;
if (!i915_request_started(request))
break;
/* More than one preemptible request may match! */
if (!match_ring(request))
break;
active = request;
break;
}
spin_unlock_irqrestore(&engine->timeline.lock, flags);
return active;
}
static void static void
i915_gem_retire_work_handler(struct work_struct *work) i915_gem_retire_work_handler(struct work_struct *work)
{ {
......
...@@ -1411,7 +1411,7 @@ static void gem_record_rings(struct i915_gpu_state *error) ...@@ -1411,7 +1411,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
error_record_engine_registers(error, engine, ee); error_record_engine_registers(error, engine, ee);
error_record_engine_execlists(engine, ee); error_record_engine_execlists(engine, ee);
request = i915_gem_find_active_request(engine); request = intel_engine_find_active_request(engine);
if (request) { if (request) {
struct i915_gem_context *ctx = request->gem_context; struct i915_gem_context *ctx = request->gem_context;
struct intel_ring *ring; struct intel_ring *ring;
......
...@@ -1545,7 +1545,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, ...@@ -1545,7 +1545,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
if (&rq->link != &engine->timeline.requests) if (&rq->link != &engine->timeline.requests)
print_request(m, rq, "\t\tlast "); print_request(m, rq, "\t\tlast ");
rq = i915_gem_find_active_request(engine); rq = intel_engine_find_active_request(engine);
if (rq) { if (rq) {
print_request(m, rq, "\t\tactive "); print_request(m, rq, "\t\tactive ");
...@@ -1712,6 +1712,51 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) ...@@ -1712,6 +1712,51 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine)
write_sequnlock_irqrestore(&engine->stats.lock, flags); write_sequnlock_irqrestore(&engine->stats.lock, flags);
} }
static bool match_ring(struct i915_request *rq)
{
struct drm_i915_private *dev_priv = rq->i915;
u32 ring = I915_READ(RING_START(rq->engine->mmio_base));
return ring == i915_ggtt_offset(rq->ring->vma);
}
struct i915_request *
intel_engine_find_active_request(struct intel_engine_cs *engine)
{
struct i915_request *request, *active = NULL;
unsigned long flags;
/*
* We are called by the error capture, reset and to dump engine
* state at random points in time. In particular, note that neither is
* crucially ordered with an interrupt. After a hang, the GPU is dead
* and we assume that no more writes can happen (we waited long enough
* for all writes that were in transaction to be flushed) - adding an
* extra delay for a recent interrupt is pointless. Hence, we do
* not need an engine->irq_seqno_barrier() before the seqno reads.
* At all other times, we must assume the GPU is still running, but
* we only care about the snapshot of this moment.
*/
spin_lock_irqsave(&engine->timeline.lock, flags);
list_for_each_entry(request, &engine->timeline.requests, link) {
if (i915_request_completed(request))
continue;
if (!i915_request_started(request))
break;
/* More than one preemptible request may match! */
if (!match_ring(request))
break;
active = request;
break;
}
spin_unlock_irqrestore(&engine->timeline.lock, flags);
return active;
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftests/mock_engine.c" #include "selftests/mock_engine.c"
#include "selftests/intel_engine_cs.c" #include "selftests/intel_engine_cs.c"
......
...@@ -1014,6 +1014,9 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine); ...@@ -1014,6 +1014,9 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine);
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine); ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine);
struct i915_request *
intel_engine_find_active_request(struct intel_engine_cs *engine);
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists) static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment