diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
3 files changed, 34 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4461336205ed..00c836154725 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3106,7 +3106,7 @@ i915_find_fence_reg(struct drm_device *dev) | |||
3106 | } | 3106 | } |
3107 | 3107 | ||
3108 | if (avail == NULL) | 3108 | if (avail == NULL) |
3109 | return NULL; | 3109 | goto deadlock; |
3110 | 3110 | ||
3111 | /* None available, try to steal one or wait for a user to finish */ | 3111 | /* None available, try to steal one or wait for a user to finish */ |
3112 | list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) { | 3112 | list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) { |
@@ -3116,7 +3116,12 @@ i915_find_fence_reg(struct drm_device *dev) | |||
3116 | return reg; | 3116 | return reg; |
3117 | } | 3117 | } |
3118 | 3118 | ||
3119 | return NULL; | 3119 | deadlock: |
3120 | /* Wait for completion of pending flips which consume fences */ | ||
3121 | if (intel_has_pending_fb_unpin(dev)) | ||
3122 | return ERR_PTR(-EAGAIN); | ||
3123 | |||
3124 | return ERR_PTR(-EDEADLK); | ||
3120 | } | 3125 | } |
3121 | 3126 | ||
3122 | /** | 3127 | /** |
@@ -3161,8 +3166,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj) | |||
3161 | } | 3166 | } |
3162 | } else if (enable) { | 3167 | } else if (enable) { |
3163 | reg = i915_find_fence_reg(dev); | 3168 | reg = i915_find_fence_reg(dev); |
3164 | if (reg == NULL) | 3169 | if (IS_ERR(reg)) |
3165 | return -EDEADLK; | 3170 | return PTR_ERR(reg); |
3166 | 3171 | ||
3167 | if (reg->obj) { | 3172 | if (reg->obj) { |
3168 | struct drm_i915_gem_object *old = reg->obj; | 3173 | struct drm_i915_gem_object *old = reg->obj; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 14b024becb91..98371eeac77c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2982,6 +2982,30 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) | |||
2982 | return pending; | 2982 | return pending; |
2983 | } | 2983 | } |
2984 | 2984 | ||
2985 | bool intel_has_pending_fb_unpin(struct drm_device *dev) | ||
2986 | { | ||
2987 | struct intel_crtc *crtc; | ||
2988 | |||
2989 | /* Note that we don't need to be called with mode_config.lock here | ||
2990 | * as our list of CRTC objects is static for the lifetime of the | ||
2991 | * device and so cannot disappear as we iterate. Similarly, we can | ||
2992 | * happily treat the predicates as racy, atomic checks as userspace | ||
2993 | * cannot claim and pin a new fb without at least acquring the | ||
2994 | * struct_mutex and so serialising with us. | ||
2995 | */ | ||
2996 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { | ||
2997 | if (atomic_read(&crtc->unpin_work_count) == 0) | ||
2998 | continue; | ||
2999 | |||
3000 | if (crtc->unpin_work) | ||
3001 | intel_wait_for_vblank(dev, crtc->pipe); | ||
3002 | |||
3003 | return true; | ||
3004 | } | ||
3005 | |||
3006 | return false; | ||
3007 | } | ||
3008 | |||
2985 | static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) | 3009 | static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) |
2986 | { | 3010 | { |
2987 | struct drm_device *dev = crtc->dev; | 3011 | struct drm_device *dev = crtc->dev; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8754db9e3d52..fbfaaba5cc3b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -626,6 +626,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, | |||
626 | 626 | ||
627 | /* intel_display.c */ | 627 | /* intel_display.c */ |
628 | const char *intel_output_name(int output); | 628 | const char *intel_output_name(int output); |
629 | bool intel_has_pending_fb_unpin(struct drm_device *dev); | ||
629 | int intel_pch_rawclk(struct drm_device *dev); | 630 | int intel_pch_rawclk(struct drm_device *dev); |
630 | void intel_mark_busy(struct drm_device *dev); | 631 | void intel_mark_busy(struct drm_device *dev); |
631 | void intel_mark_fb_busy(struct drm_i915_gem_object *obj, | 632 | void intel_mark_fb_busy(struct drm_i915_gem_object *obj, |