diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 39 |
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 | ||
43 | static inline int ring_space(struct intel_ring_buffer *ring) | 43 | static 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 | ||
51 | static inline int ring_space(struct intel_ring_buffer *ring) | ||
52 | { | ||
53 | return __ring_space(ring->head & HEAD_ADDR, ring->tail, ring->size); | ||
54 | } | ||
55 | |||
51 | static bool intel_ring_stopped(struct intel_ring_buffer *ring) | 56 | static 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) | |||
1482 | static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n) | 1487 | static 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 | ||