aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-05 04:07:33 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-05-07 19:23:34 -0400
commit1cf0ba14740d96fbf6f58a201f000a34b74f4725 (patch)
treed96d157f27c06eb90f91aed6c95aaa0d319c5898 /drivers/gpu/drm/i915/intel_ringbuffer.c
parentdcfe050659bbd02e3b18d4b19eb0bcc8d0072bb0 (diff)
drm/i915: Flush request queue when waiting for ring space
During the review of commit 1f70999f9052f5a1b0ce1a55aff3808f2ec9fe42 Author: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon Jan 27 22:43:07 2014 +0000 drm/i915: Prevent recursion by retiring requests when the ring is full Ville raised the point that our interaction with request->tail was likely to foul up other uses elsewhere (such as hang check comparing ACTHD against requests). However, we also need to restore the implicit retire requests that certain test cases depend upon (e.g. igt/gem_exec_lut_handle), this raises the spectre that the ppgtt will randomly call i915_gpu_idle() and recurse back into intel_ring_begin(). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=78023 Reviewed-by: Brad Volkin <bradley.d.volkin@intel.com> [danvet: Remove now unused 'tail' variable as spotted by Brad.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c39
1 files changed, 14 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index e6c7a4dfea51..9907d66becdd 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -40,14 +40,19 @@
40 */ 40 */
41#define CACHELINE_BYTES 64 41#define CACHELINE_BYTES 64
42 42
43static inline int ring_space(struct intel_ring_buffer *ring) 43static inline int __ring_space(int head, int tail, int size)
44{ 44{
45 int space = (ring->head & HEAD_ADDR) - (ring->tail + I915_RING_FREE_SPACE); 45 int space = head - (tail + I915_RING_FREE_SPACE);
46 if (space < 0) 46 if (space < 0)
47 space += ring->size; 47 space += size;
48 return space; 48 return space;
49} 49}
50 50
51static inline int ring_space(struct intel_ring_buffer *ring)
52{
53 return __ring_space(ring->head & HEAD_ADDR, ring->tail, ring->size);
54}
55
51static bool intel_ring_stopped(struct intel_ring_buffer *ring) 56static bool intel_ring_stopped(struct intel_ring_buffer *ring)
52{ 57{
53 struct drm_i915_private *dev_priv = ring->dev->dev_private; 58 struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -1482,7 +1487,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
1482static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) 1487static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
1483{ 1488{
1484 struct drm_i915_gem_request *request; 1489 struct drm_i915_gem_request *request;
1485 u32 seqno = 0, tail; 1490 u32 seqno = 0;
1486 int ret; 1491 int ret;
1487 1492
1488 if (ring->last_retired_head != -1) { 1493 if (ring->last_retired_head != -1) {
@@ -1495,26 +1500,10 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
1495 } 1500 }
1496 1501
1497 list_for_each_entry(request, &ring->request_list, list) { 1502 list_for_each_entry(request, &ring->request_list, list) {
1498 int space; 1503 if (__ring_space(request->tail, ring->tail, ring->size) >= n) {
1499
1500 if (request->tail == -1)
1501 continue;
1502
1503 space = request->tail - (ring->tail + I915_RING_FREE_SPACE);
1504 if (space < 0)
1505 space += ring->size;
1506 if (space >= n) {
1507 seqno = request->seqno; 1504 seqno = request->seqno;
1508 tail = request->tail;
1509 break; 1505 break;
1510 } 1506 }
1511
1512 /* Consume this request in case we need more space than
1513 * is available and so need to prevent a race between
1514 * updating last_retired_head and direct reads of
1515 * I915_RING_HEAD. It also provides a nice sanity check.
1516 */
1517 request->tail = -1;
1518 } 1507 }
1519 1508
1520 if (seqno == 0) 1509 if (seqno == 0)
@@ -1524,11 +1513,11 @@ static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
1524 if (ret) 1513 if (ret)
1525 return ret; 1514 return ret;
1526 1515
1527 ring->head = tail; 1516 i915_gem_retire_requests_ring(ring);
1528 ring->space = ring_space(ring); 1517 ring->head = ring->last_retired_head;
1529 if (WARN_ON(ring->space < n)) 1518 ring->last_retired_head = -1;
1530 return -ENOSPC;
1531 1519
1520 ring->space = ring_space(ring);
1532 return 0; 1521 return 0;
1533} 1522}
1534 1523