aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_lrc.c
diff options
context:
space:
mode:
authorDave Gordon <david.s.gordon@intel.com>2014-11-27 06:22:49 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-12-03 03:35:26 -0500
commitebd0fd4bef6384dd422d6480b0d5b10b7bfe829a (patch)
treef6d371b1cd2e61daf6a5c64ba9bd1e30d515fccf /drivers/gpu/drm/i915/intel_lrc.c
parent4f54741e07f9c4791f06a3d151b56ece08b27c20 (diff)
drm/i915: Consolidate ring freespace calculations
There are numerous places in the code where the driver's idea of how much space is left in a ring is updated using the driver's latest notions of the positions of 'head' and 'tail' for the ring. Among them are some that update one or both of these values before (re)doing the calculation. In particular, there are four different places in the code where 'last_retired_head' is copied to 'head' and then set to -1; and two of these do not have a guard to check that it has actually been updated since last time it was consumed, leaving the possibility that the dummy -1 can be transferred from 'last_retired_head' to 'head', causing the space calculation to produce 'impossible' results (previously seen on Android/VLV). This code therefore consolidates all the calculation and updating of these values, such that there is only one place where the ring space is updated, and it ALWAYS uses (and consumes) 'last_retired_head' if (and ONLY if) it has been updated since the last call. Signed-off-by: Dave Gordon <david.s.gordon@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lrc.c')
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c25
1 files changed, 7 insertions, 18 deletions
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index b13221b86b05..828cba49cf01 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -925,14 +925,8 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf,
925 struct drm_i915_gem_request *request; 925 struct drm_i915_gem_request *request;
926 int ret; 926 int ret;
927 927
928 if (ringbuf->last_retired_head != -1) { 928 if (intel_ring_space(ringbuf) >= bytes)
929 ringbuf->head = ringbuf->last_retired_head; 929 return 0;
930 ringbuf->last_retired_head = -1;
931
932 ringbuf->space = intel_ring_space(ringbuf);
933 if (ringbuf->space >= bytes)
934 return 0;
935 }
936 930
937 list_for_each_entry(request, &ring->request_list, list) { 931 list_for_each_entry(request, &ring->request_list, list) {
938 /* 932 /*
@@ -959,11 +953,8 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf,
959 return ret; 953 return ret;
960 954
961 i915_gem_retire_requests_ring(ring); 955 i915_gem_retire_requests_ring(ring);
962 ringbuf->head = ringbuf->last_retired_head;
963 ringbuf->last_retired_head = -1;
964 956
965 ringbuf->space = intel_ring_space(ringbuf); 957 return intel_ring_space(ringbuf) >= bytes ? 0 : -ENOSPC;
966 return 0;
967} 958}
968 959
969static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, 960static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf,
@@ -989,12 +980,10 @@ static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf,
989 * case by choosing an insanely large timeout. */ 980 * case by choosing an insanely large timeout. */
990 end = jiffies + 60 * HZ; 981 end = jiffies + 60 * HZ;
991 982
983 ret = 0;
992 do { 984 do {
993 ringbuf->space = intel_ring_space(ringbuf); 985 if (intel_ring_space(ringbuf) >= bytes)
994 if (ringbuf->space >= bytes) {
995 ret = 0;
996 break; 986 break;
997 }
998 987
999 msleep(1); 988 msleep(1);
1000 989
@@ -1035,7 +1024,7 @@ static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf)
1035 iowrite32(MI_NOOP, virt++); 1024 iowrite32(MI_NOOP, virt++);
1036 1025
1037 ringbuf->tail = 0; 1026 ringbuf->tail = 0;
1038 ringbuf->space = intel_ring_space(ringbuf); 1027 intel_ring_update_space(ringbuf);
1039 1028
1040 return 0; 1029 return 0;
1041} 1030}
@@ -1885,8 +1874,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
1885 ringbuf->effective_size = ringbuf->size; 1874 ringbuf->effective_size = ringbuf->size;
1886 ringbuf->head = 0; 1875 ringbuf->head = 0;
1887 ringbuf->tail = 0; 1876 ringbuf->tail = 0;
1888 ringbuf->space = ringbuf->size;
1889 ringbuf->last_retired_head = -1; 1877 ringbuf->last_retired_head = -1;
1878 intel_ring_update_space(ringbuf);
1890 1879
1891 if (ringbuf->obj == NULL) { 1880 if (ringbuf->obj == NULL) {
1892 ret = intel_alloc_ringbuffer_obj(dev, ringbuf); 1881 ret = intel_alloc_ringbuffer_obj(dev, ringbuf);