Commit 3c0e234c847318304c12f9e7fffac7e1cf3db3ff

Authored by Chris Wilson
Committed by Daniel Vetter
1 parent 1823521d2b

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: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 3 changed files with 15 additions and 5 deletions Side-by-side Diff

drivers/gpu/drm/i915/i915_gem.c
... ... @@ -2041,8 +2041,8 @@
2041 2041 if (ret)
2042 2042 return ret;
2043 2043  
2044   - request = kmalloc(sizeof(*request), GFP_KERNEL);
2045   - if (request == NULL)
  2044 + request = ring->preallocated_lazy_request;
  2045 + if (WARN_ON(request == NULL))
2046 2046 return -ENOMEM;
2047 2047  
2048 2048 /* Record the position of the start of the request so that
2049 2049  
... ... @@ -2053,10 +2053,8 @@
2053 2053 request_ring_position = intel_ring_get_tail(ring);
2054 2054  
2055 2055 ret = ring->add_request(ring);
2056   - if (ret) {
2057   - kfree(request);
  2056 + if (ret)
2058 2057 return ret;
2059   - }
2060 2058  
2061 2059 request->seqno = intel_ring_get_seqno(ring);
2062 2060 request->ring = ring;
... ... @@ -2095,6 +2093,7 @@
2095 2093  
2096 2094 trace_i915_gem_request_add(ring, request->seqno);
2097 2095 ring->outstanding_lazy_seqno = 0;
  2096 + ring->preallocated_lazy_request = NULL;
2098 2097  
2099 2098 if (!dev_priv->ums.mm_suspended) {
2100 2099 i915_queue_hangcheck(ring->dev);
drivers/gpu/drm/i915/intel_ringbuffer.c
... ... @@ -1498,6 +1498,16 @@
1498 1498 if (ring->outstanding_lazy_seqno)
1499 1499 return 0;
1500 1500  
  1501 + if (ring->preallocated_lazy_request == NULL) {
  1502 + struct drm_i915_gem_request *request;
  1503 +
  1504 + request = kmalloc(sizeof(*request), GFP_KERNEL);
  1505 + if (request == NULL)
  1506 + return -ENOMEM;
  1507 +
  1508 + ring->preallocated_lazy_request = request;
  1509 + }
  1510 +
1501 1511 return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
1502 1512 }
1503 1513  
drivers/gpu/drm/i915/intel_ringbuffer.h
... ... @@ -140,6 +140,7 @@
140 140 /**
141 141 * Do we have some not yet emitted requests outstanding?
142 142 */
  143 + struct drm_i915_gem_request *preallocated_lazy_request;
143 144 u32 outstanding_lazy_seqno;
144 145 bool gpu_caches_dirty;
145 146 bool fbc_dirty;