Commit 1f70999f authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 011cf577
...@@ -1430,28 +1430,16 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) ...@@ -1430,28 +1430,16 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
cleanup_status_page(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) static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
{ {
struct drm_i915_gem_request *request; struct drm_i915_gem_request *request;
u32 seqno = 0; u32 seqno = 0, tail;
int ret; int ret;
i915_gem_retire_requests_ring(ring);
if (ring->last_retired_head != -1) { if (ring->last_retired_head != -1) {
ring->head = ring->last_retired_head; ring->head = ring->last_retired_head;
ring->last_retired_head = -1; ring->last_retired_head = -1;
ring->space = ring_space(ring); ring->space = ring_space(ring);
if (ring->space >= n) if (ring->space >= n)
return 0; return 0;
...@@ -1468,6 +1456,7 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) ...@@ -1468,6 +1456,7 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
space += ring->size; space += ring->size;
if (space >= n) { if (space >= n) {
seqno = request->seqno; seqno = request->seqno;
tail = request->tail;
break; break;
} }
...@@ -1482,15 +1471,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) ...@@ -1482,15 +1471,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
if (seqno == 0) if (seqno == 0)
return -ENOSPC; return -ENOSPC;
ret = intel_ring_wait_seqno(ring, seqno); ret = i915_wait_seqno(ring, seqno);
if (ret) if (ret)
return ret; return ret;
if (WARN_ON(ring->last_retired_head == -1)) ring->head = tail;
return -ENOSPC;
ring->head = ring->last_retired_head;
ring->last_retired_head = -1;
ring->space = ring_space(ring); ring->space = ring_space(ring);
if (WARN_ON(ring->space < n)) if (WARN_ON(ring->space < n))
return -ENOSPC; return -ENOSPC;
......
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