diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-01-20 10:17:37 +0000 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-01-22 10:34:41 +0100 |
commit | 74e21ac2ccdc5e8f310d536ffe66d22571ece5c5 (patch) | |
tree | 0da3fc9fdfceb187bb116c9759fa4e28f19b841a /drivers/gpu/drm/i915/i915_gem_evict.c | |
parent | 5dce5b9387a06eb9301fa1cede07922a5a4d7a29 (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/drm/i915/i915_gem_evict.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 27 |
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 @@ */ #include <drm/drmP.h> -#include "i915_drv.h" #include <drm/i915_drm.h> + +#include "i915_drv.h" +#include "intel_drv.h" #include "i915_trace.h" static bool @@ -53,6 +55,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, struct list_head eviction_list, unwind_list; struct i915_vma *vma; int ret = 0; + int pass = 0; trace_i915_gem_evict(dev, min_size, alignment, mappable); @@ -119,14 +122,24 @@ none: /* Can we unpin some objects such as idle hw contents, * or pending flips? */ - ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev); - if (ret) - return ret; + if (nonblocking) + return -ENOSPC; /* Only idle the GPU and repeat the search once */ - i915_gem_retire_requests(dev); - nonblocking = true; - goto search_again; + if (pass++ == 0) { + ret = i915_gpu_idle(dev); + if (ret) + return ret; + + i915_gem_retire_requests(dev); + goto search_again; + } + + /* If we still have pending pageflip completions, drop + * back to userspace to give our workqueues time to + * acquire our locks and unpin the old scanouts. + */ + return intel_has_pending_fb_unpin(dev) ? -EAGAIN : -ENOSPC; found: /* drm_mm doesn't allow any other other operations while |