diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 41d5a99..dfd8392 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3214,7 +3214,7 @@ i915_find_fence_reg(struct drm_device *dev) } if (avail == NULL) - return NULL; + goto deadlock; /* None available, try to steal one or wait for a user to finish */ list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) { @@ -3224,7 +3224,24 @@ i915_find_fence_reg(struct drm_device *dev) return reg; } - return NULL; +deadlock: + DRM_ERROR("no free fences..\n"); + { + struct intel_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + if (atomic_read(&crtc->unpin_work_count) == 0) + continue; + + if (crtc->unpin_work) + intel_wait_for_vblank(dev, crtc->pipe); + + DRM_ERROR("pending flip, try again\n"); + return ERR_PTR(-EAGAIN); + } + } + + return ERR_PTR(-EDEADLK); } /** @@ -3269,8 +3286,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj) } } else if (enable) { reg = i915_find_fence_reg(dev); - if (reg == NULL) - return -EDEADLK; + if (IS_ERR(reg)) + return PTR_ERR(reg); if (reg->obj) { struct drm_i915_gem_object *old = reg->obj;