aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c25
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c42
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h1
3 files changed, 30 insertions, 38 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);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 2ac382ac6bbb..e0b76fff8df2 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -58,10 +58,21 @@ int __intel_ring_space(int head, int tail, int size)
58 return space - I915_RING_FREE_SPACE; 58 return space - I915_RING_FREE_SPACE;
59} 59}
60 60
61void intel_ring_update_space(struct intel_ringbuffer *ringbuf)
62{
63 if (ringbuf->last_retired_head != -1) {
64 ringbuf->head = ringbuf->last_retired_head;
65 ringbuf->last_retired_head = -1;
66 }
67
68 ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR,
69 ringbuf->tail, ringbuf->size);
70}
71
61int intel_ring_space(struct intel_ringbuffer *ringbuf) 72int intel_ring_space(struct intel_ringbuffer *ringbuf)
62{ 73{
63 return __intel_ring_space(ringbuf->head & HEAD_ADDR, 74 intel_ring_update_space(ringbuf);
64 ringbuf->tail, ringbuf->size); 75 return ringbuf->space;
65} 76}
66 77
67bool intel_ring_stopped(struct intel_engine_cs *ring) 78bool intel_ring_stopped(struct intel_engine_cs *ring)
@@ -589,10 +600,10 @@ static int init_ring_common(struct intel_engine_cs *ring)
589 goto out; 600 goto out;
590 } 601 }
591 602
603 ringbuf->last_retired_head = -1;
592 ringbuf->head = I915_READ_HEAD(ring); 604 ringbuf->head = I915_READ_HEAD(ring);
593 ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; 605 ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
594 ringbuf->space = intel_ring_space(ringbuf); 606 intel_ring_update_space(ringbuf);
595 ringbuf->last_retired_head = -1;
596 607
597 memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); 608 memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
598 609
@@ -1901,14 +1912,8 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
1901 struct drm_i915_gem_request *request; 1912 struct drm_i915_gem_request *request;
1902 int ret; 1913 int ret;
1903 1914
1904 if (ringbuf->last_retired_head != -1) { 1915 if (intel_ring_space(ringbuf) >= n)
1905 ringbuf->head = ringbuf->last_retired_head; 1916 return 0;
1906 ringbuf->last_retired_head = -1;
1907
1908 ringbuf->space = intel_ring_space(ringbuf);
1909 if (ringbuf->space >= n)
1910 return 0;
1911 }
1912 1917
1913 list_for_each_entry(request, &ring->request_list, list) { 1918 list_for_each_entry(request, &ring->request_list, list) {
1914 if (__intel_ring_space(request->tail, ringbuf->tail, 1919 if (__intel_ring_space(request->tail, ringbuf->tail,
@@ -1925,10 +1930,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n)
1925 return ret; 1930 return ret;
1926 1931
1927 i915_gem_retire_requests_ring(ring); 1932 i915_gem_retire_requests_ring(ring);
1928 ringbuf->head = ringbuf->last_retired_head;
1929 ringbuf->last_retired_head = -1;
1930 1933
1931 ringbuf->space = intel_ring_space(ringbuf);
1932 return 0; 1934 return 0;
1933} 1935}
1934 1936
@@ -1954,14 +1956,14 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
1954 * case by choosing an insanely large timeout. */ 1956 * case by choosing an insanely large timeout. */
1955 end = jiffies + 60 * HZ; 1957 end = jiffies + 60 * HZ;
1956 1958
1959 ret = 0;
1957 trace_i915_ring_wait_begin(ring); 1960 trace_i915_ring_wait_begin(ring);
1958 do { 1961 do {
1962 if (intel_ring_space(ringbuf) >= n)
1963 break;
1959 ringbuf->head = I915_READ_HEAD(ring); 1964 ringbuf->head = I915_READ_HEAD(ring);
1960 ringbuf->space = intel_ring_space(ringbuf); 1965 if (intel_ring_space(ringbuf) >= n)
1961 if (ringbuf->space >= n) {
1962 ret = 0;
1963 break; 1966 break;
1964 }
1965 1967
1966 msleep(1); 1968 msleep(1);
1967 1969
@@ -2002,7 +2004,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)
2002 iowrite32(MI_NOOP, virt++); 2004 iowrite32(MI_NOOP, virt++);
2003 2005
2004 ringbuf->tail = 0; 2006 ringbuf->tail = 0;
2005 ringbuf->space = intel_ring_space(ringbuf); 2007 intel_ring_update_space(ringbuf);
2006 2008
2007 return 0; 2009 return 0;
2008} 2010}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 39e303d83e91..17e9011dff22 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -407,6 +407,7 @@ static inline void intel_ring_advance(struct intel_engine_cs *ring)
407 ringbuf->tail &= ringbuf->size - 1; 407 ringbuf->tail &= ringbuf->size - 1;
408} 408}
409int __intel_ring_space(int head, int tail, int size); 409int __intel_ring_space(int head, int tail, int size);
410void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
410int intel_ring_space(struct intel_ringbuffer *ringbuf); 411int intel_ring_space(struct intel_ringbuffer *ringbuf);
411bool intel_ring_stopped(struct intel_engine_cs *ring); 412bool intel_ring_stopped(struct intel_engine_cs *ring);
412void __intel_ring_advance(struct intel_engine_cs *ring); 413void __intel_ring_advance(struct intel_engine_cs *ring);