Move the final interesting chunk from i915_wait_seqno into a timed variant. The timed variant can take a NULL or 0 timeout argument to preserve the old behavior, and this allowing the old (still useful function) to call directly into the timed variant. This code does not require struct_mutex, therefore it can wait on events without holding the lock. Signed-off-by: Ben Widawsky <benjamin.widawsky at intel.com> --- drivers/gpu/drm/i915/i915_gem.c | 53 ++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7bfad04..e446d9c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1879,6 +1879,40 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, } } +static int +i915_seqno_wait_timed(struct intel_ring_buffer *ring, u32 seqno, + bool interruptible, long *timeout) +{ + bool wait_forever = false; + int ret = 0; + + BUG_ON(seqno == ring->outstanding_lazy_request); + + if (timeout == NULL || ((*timeout) < 0)) + wait_forever = true; + + if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { + trace_i915_gem_request_wait_begin(ring, seqno); + + if (WARN_ON(!ring->irq_get(ring))) + return -EBUSY; + + do { + long time = wait_forever ? SEQNO_WAIT_DEFAULT : *timeout; + ret = __wait_seqno(ring, seqno, + interruptible, + &time); + if (ret == 0 && timeout) + *timeout = time; + } while (ret == -ETIME && wait_forever); + + ring->irq_put(ring); + trace_i915_gem_request_wait_end(ring, seqno); + } + + return ret; +} + /** * Waits for a sequence number to be signaled, and cleans up the * request and object lists appropriately for that event. @@ -1920,23 +1954,8 @@ i915_wait_request(struct intel_ring_buffer *ring, seqno = request->seqno; } - - if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { - trace_i915_gem_request_wait_begin(ring, seqno); - - if (WARN_ON(!ring->irq_get(ring))) - return -EBUSY; - - do { - long time = SEQNO_WAIT_DEFAULT; - ret = __wait_seqno(ring, seqno, - dev_priv->mm.interruptible, - &time); - } while (ret == -ETIME); - - ring->irq_put(ring); - trace_i915_gem_request_wait_end(ring, seqno); - } + ret = i915_seqno_wait_timed(ring, seqno, dev_priv->mm.interruptible, + NULL); if (atomic_read(&dev_priv->mm.wedged)) ret = -EAGAIN; -- 1.7.10