drm/i915: Prevent recursion by retiring requests when the ring is full

As the VM do not track activity of objects and instead use a large
hammer to forcibly idle and evict all of their associated objects when
one is released, it is possible for that to cause a recursion when we
need to wait for free space on a ring and call retire requests.
(intel_ring_begin -> intel_ring_wait_request ->
i915_gem_retire_requests_ring -> i915_gem_context_free ->
i915_gem_evict_vm -> i915_gpu_idle -> intel_ring_begin etc)

In order to remove the requirement for calling retire-requests from
intel_ring_wait_request, we have to inline a couple of steps from
retiring requests, notably we have to record the position of the request
we wait for and use that to update the available ring space.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Chris Wilson 2014-01-27 22:43:07 +00:00 committed by Daniel Vetter
parent 011cf577b2
commit 1f70999f90

View File

@ -1430,28 +1430,16 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
cleanup_status_page(ring);
}
static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
{
int ret;
ret = i915_wait_seqno(ring, seqno);
if (!ret)
i915_gem_retire_requests_ring(ring);
return ret;
}
static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
{
struct drm_i915_gem_request *request;
u32 seqno = 0;
u32 seqno = 0, tail;
int ret;
i915_gem_retire_requests_ring(ring);
if (ring->last_retired_head != -1) {
ring->head = ring->last_retired_head;
ring->last_retired_head = -1;
ring->space = ring_space(ring);
if (ring->space >= n)
return 0;
@ -1468,6 +1456,7 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
space += ring->size;
if (space >= n) {
seqno = request->seqno;
tail = request->tail;
break;
}
@ -1482,15 +1471,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
if (seqno == 0)
return -ENOSPC;
ret = intel_ring_wait_seqno(ring, seqno);
ret = i915_wait_seqno(ring, seqno);
if (ret)
return ret;
if (WARN_ON(ring->last_retired_head == -1))
return -ENOSPC;
ring->head = ring->last_retired_head;
ring->last_retired_head = -1;
ring->head = tail;
ring->space = ring_space(ring);
if (WARN_ON(ring->space < n))
return -ENOSPC;