drm/i915/overlay: Pass interruptible to switch_off()

During DPMS we currently do not want the overlay code to be
interruptible, so pass that information down and only take the
uninterrruptible paths.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Chris Wilson 2010-08-12 13:50:28 +01:00
parent 106dadacbe
commit 5dcdbcb06b
3 changed files with 21 additions and 35 deletions

View File

@ -2223,33 +2223,17 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
{ {
struct intel_overlay *overlay;
int ret;
if (!enable && intel_crtc->overlay) { if (!enable && intel_crtc->overlay) {
overlay = intel_crtc->overlay; struct intel_overlay *overlay = intel_crtc->overlay;
mutex_lock(&overlay->dev->struct_mutex);
for (;;) {
ret = intel_overlay_switch_off(overlay);
if (ret == 0)
break;
ret = intel_overlay_recover_from_interrupt(overlay, 0); mutex_lock(&overlay->dev->struct_mutex);
if (ret != 0) { (void) intel_overlay_switch_off(overlay, false);
/* overlay doesn't react anymore. Usually
* results in a black screen and an unkillable
* X server. */
BUG();
overlay->hw_wedged = HW_WEDGED;
break;
}
}
mutex_unlock(&overlay->dev->struct_mutex); mutex_unlock(&overlay->dev->struct_mutex);
} }
/* Let userspace switch the overlay on again. In most cases userspace
* has to recompute where to put it anyway. */
return; /* Let userspace switch the overlay on again. In most cases userspace
* has to recompute where to put it anyway.
*/
} }
static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)

View File

@ -287,8 +287,7 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
extern void intel_setup_overlay(struct drm_device *dev); extern void intel_setup_overlay(struct drm_device *dev);
extern void intel_cleanup_overlay(struct drm_device *dev); extern void intel_cleanup_overlay(struct drm_device *dev);
extern int intel_overlay_switch_off(struct intel_overlay *overlay); extern int intel_overlay_switch_off(struct intel_overlay *overlay,
extern int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
bool interruptible); bool interruptible);
extern int intel_overlay_put_image(struct drm_device *dev, void *data, extern int intel_overlay_put_image(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);

View File

@ -365,7 +365,8 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
} }
/* overlay needs to be disabled in OCMD reg */ /* overlay needs to be disabled in OCMD reg */
static int intel_overlay_off(struct intel_overlay *overlay) static int intel_overlay_off(struct intel_overlay *overlay,
bool interruptible)
{ {
struct drm_device *dev = overlay->dev; struct drm_device *dev = overlay->dev;
u32 flip_addr = overlay->flip_addr; u32 flip_addr = overlay->flip_addr;
@ -394,7 +395,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
ADVANCE_LP_RING(); ADVANCE_LP_RING();
return intel_overlay_do_wait_request(overlay, request, true, return intel_overlay_do_wait_request(overlay, request, interruptible,
SWITCH_OFF); SWITCH_OFF);
} }
@ -427,7 +428,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
/* recover from an interruption due to a signal /* recover from an interruption due to a signal
* We have to be careful not to repeat work forever an make forward progess. */ * We have to be careful not to repeat work forever an make forward progess. */
int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay, static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
bool interruptible) bool interruptible)
{ {
struct drm_device *dev = overlay->dev; struct drm_device *dev = overlay->dev;
@ -855,17 +856,19 @@ out_unpin:
return ret; return ret;
} }
int intel_overlay_switch_off(struct intel_overlay *overlay) int intel_overlay_switch_off(struct intel_overlay *overlay,
bool interruptible)
{ {
int ret;
struct overlay_registers *regs; struct overlay_registers *regs;
struct drm_device *dev = overlay->dev; struct drm_device *dev = overlay->dev;
int ret;
BUG_ON(!mutex_is_locked(&dev->struct_mutex)); BUG_ON(!mutex_is_locked(&dev->struct_mutex));
BUG_ON(!mutex_is_locked(&dev->mode_config.mutex)); BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
if (overlay->hw_wedged) { if (overlay->hw_wedged) {
ret = intel_overlay_recover_from_interrupt(overlay, 1); ret = intel_overlay_recover_from_interrupt(overlay,
interruptible);
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
@ -881,7 +884,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
regs->OCMD = 0; regs->OCMD = 0;
intel_overlay_unmap_regs(overlay, regs); intel_overlay_unmap_regs(overlay, regs);
ret = intel_overlay_off(overlay); ret = intel_overlay_off(overlay, interruptible);
if (ret != 0) if (ret != 0)
return ret; return ret;
@ -1097,7 +1100,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
ret = intel_overlay_switch_off(overlay); ret = intel_overlay_switch_off(overlay, true);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
@ -1135,7 +1138,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
if (overlay->crtc != crtc) { if (overlay->crtc != crtc) {
struct drm_display_mode *mode = &crtc->base.mode; struct drm_display_mode *mode = &crtc->base.mode;
ret = intel_overlay_switch_off(overlay); ret = intel_overlay_switch_off(overlay, true);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;