aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
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