Commit 3c0e234c authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

drm/i915; Preallocate the lazy request

It is possible for us to be forced to perform an allocation for the lazy
request whilst running the shrinker. This allocation may fail, leaving
us unable to reclaim any memory leading to premature OOM. A neat
solution to the problem is to preallocate the request at the same time
as acquiring the seqno for the ring transaction. This means that we can
report ENOMEM prior to touching the rings.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 1823521d
...@@ -2041,8 +2041,8 @@ int __i915_add_request(struct intel_ring_buffer *ring, ...@@ -2041,8 +2041,8 @@ int __i915_add_request(struct intel_ring_buffer *ring,
if (ret) if (ret)
return ret; return ret;
request = kmalloc(sizeof(*request), GFP_KERNEL); request = ring->preallocated_lazy_request;
if (request == NULL) if (WARN_ON(request == NULL))
return -ENOMEM; return -ENOMEM;
/* Record the position of the start of the request so that /* Record the position of the start of the request so that
...@@ -2053,10 +2053,8 @@ int __i915_add_request(struct intel_ring_buffer *ring, ...@@ -2053,10 +2053,8 @@ int __i915_add_request(struct intel_ring_buffer *ring,
request_ring_position = intel_ring_get_tail(ring); request_ring_position = intel_ring_get_tail(ring);
ret = ring->add_request(ring); ret = ring->add_request(ring);
if (ret) { if (ret)
kfree(request);
return ret; return ret;
}
request->seqno = intel_ring_get_seqno(ring); request->seqno = intel_ring_get_seqno(ring);
request->ring = ring; request->ring = ring;
...@@ -2095,6 +2093,7 @@ int __i915_add_request(struct intel_ring_buffer *ring, ...@@ -2095,6 +2093,7 @@ int __i915_add_request(struct intel_ring_buffer *ring,
trace_i915_gem_request_add(ring, request->seqno); trace_i915_gem_request_add(ring, request->seqno);
ring->outstanding_lazy_seqno = 0; ring->outstanding_lazy_seqno = 0;
ring->preallocated_lazy_request = NULL;
if (!dev_priv->ums.mm_suspended) { if (!dev_priv->ums.mm_suspended) {
i915_queue_hangcheck(ring->dev); i915_queue_hangcheck(ring->dev);
......
...@@ -1498,6 +1498,16 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring) ...@@ -1498,6 +1498,16 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
if (ring->outstanding_lazy_seqno) if (ring->outstanding_lazy_seqno)
return 0; return 0;
if (ring->preallocated_lazy_request == NULL) {
struct drm_i915_gem_request *request;
request = kmalloc(sizeof(*request), GFP_KERNEL);
if (request == NULL)
return -ENOMEM;
ring->preallocated_lazy_request = request;
}
return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
} }
......
...@@ -140,6 +140,7 @@ struct intel_ring_buffer { ...@@ -140,6 +140,7 @@ struct intel_ring_buffer {
/** /**
* Do we have some not yet emitted requests outstanding? * Do we have some not yet emitted requests outstanding?
*/ */
struct drm_i915_gem_request *preallocated_lazy_request;
u32 outstanding_lazy_seqno; u32 outstanding_lazy_seqno;
bool gpu_caches_dirty; bool gpu_caches_dirty;
bool fbc_dirty; bool fbc_dirty;
......
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