aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-01-20 05:17:37 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-01-22 04:34:41 -0500
commit74e21ac2ccdc5e8f310d536ffe66d22571ece5c5 (patch)
tree0da3fc9fdfceb187bb116c9759fa4e28f19b841a /drivers/gpu
parent5dce5b9387a06eb9301fa1cede07922a5a4d7a29 (diff)
drm/i915: Repeat evictions whilst pageflip completions are outstanding
Since an old pageflip will keep its scanout buffer object pinned until it has executed its unpin task on the common workqueue, we can clog up our GGTT with stale pinned objects. As we cannot flush those workqueues without dropping our locks, we have to resort to falling back to userspace and telling them to repeat the operation in order to have a chance to run our workqueues and free up the required memory. If we fail, then we are forced to report ENOSPC back to userspace causing the operation to fail and best-case scenario is that it introduces temporary corruption. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Jon Bloomfield <jon.bloomfield@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 8f3adc7d0dc8..2ca280f9ee53 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -27,8 +27,10 @@
27 */ 27 */
28 28
29#include <drm/drmP.h> 29#include <drm/drmP.h>
30#include "i915_drv.h"
31#include <drm/i915_drm.h> 30#include <drm/i915_drm.h>
31
32#include "i915_drv.h"
33#include "intel_drv.h"
32#include "i915_trace.h" 34#include "i915_trace.h"
33 35
34static bool 36static bool
@@ -53,6 +55,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
53 struct list_head eviction_list, unwind_list; 55 struct list_head eviction_list, unwind_list;
54 struct i915_vma *vma; 56 struct i915_vma *vma;
55 int ret = 0; 57 int ret = 0;
58 int pass = 0;
56 59
57 trace_i915_gem_evict(dev, min_size, alignment, mappable); 60 trace_i915_gem_evict(dev, min_size, alignment, mappable);
58 61
@@ -119,14 +122,24 @@ none:
119 /* Can we unpin some objects such as idle hw contents, 122 /* Can we unpin some objects such as idle hw contents,
120 * or pending flips? 123 * or pending flips?
121 */ 124 */
122 ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev); 125 if (nonblocking)
123 if (ret) 126 return -ENOSPC;
124 return ret;
125 127
126 /* Only idle the GPU and repeat the search once */ 128 /* Only idle the GPU and repeat the search once */
127 i915_gem_retire_requests(dev); 129 if (pass++ == 0) {
128 nonblocking = true; 130 ret = i915_gpu_idle(dev);
129 goto search_again; 131 if (ret)
132 return ret;
133
134 i915_gem_retire_requests(dev);
135 goto search_again;
136 }
137
138 /* If we still have pending pageflip completions, drop
139 * back to userspace to give our workqueues time to
140 * acquire our locks and unpin the old scanouts.
141 */
142 return intel_has_pending_fb_unpin(dev) ? -EAGAIN : -ENOSPC;
130 143
131found: 144found:
132 /* drm_mm doesn't allow any other other operations while 145 /* drm_mm doesn't allow any other other operations while