drm: Propagate failure from setting crtc base.

Check the error paths within intel_pipe_set_base() to first cleanup and
then report back the error.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
Chris Wilson 2009-02-11 13:25:09 +00:00 committed by Dave Airlie
parent e62fb64e61
commit 5c3b82e2b2
3 changed files with 69 additions and 40 deletions

View File

@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (drm_mode_equal(&saved_mode, &crtc->mode)) { if (drm_mode_equal(&saved_mode, &crtc->mode)) {
if (saved_x != crtc->x || saved_y != crtc->y || if (saved_x != crtc->x || saved_y != crtc->y ||
depth_changed || bpp_changed) { depth_changed || bpp_changed) {
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb); old_fb);
goto done; goto done;
} }
} }
@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
/* Set up the DPLL and any encoders state that needs to adjust or depend /* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL. * on the DPLL.
*/ */
crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
if (!ret)
goto done;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (!drm_crtc_helper_set_mode(set->crtc, set->mode, if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y, set->x, set->y,
old_fb)) { old_fb)) {
DRM_ERROR("failed to set mode on crtc %p\n",
set->crtc);
ret = -EINVAL; ret = -EINVAL;
goto fail_set_mode; goto fail_set_mode;
} }
@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
old_fb = set->crtc->fb; old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb) if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb; set->crtc->fb = set->fb;
crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, old_fb);
if (ret != 0)
goto fail_set_mode;
} }
kfree(save_encoders); kfree(save_encoders);

View File

@ -343,7 +343,7 @@ intel_wait_for_vblank(struct drm_device *dev)
udelay(20000); udelay(20000);
} }
static void static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
@ -361,11 +361,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr, alignment; u32 dspcntr, alignment;
int ret;
/* no fb bound */ /* no fb bound */
if (!crtc->fb) { if (!crtc->fb) {
DRM_DEBUG("No FB bound\n"); DRM_DEBUG("No FB bound\n");
return; return 0;
}
switch (pipe) {
case 0:
case 1:
break;
default:
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
return -EINVAL;
} }
intel_fb = to_intel_framebuffer(crtc->fb); intel_fb = to_intel_framebuffer(crtc->fb);
@ -383,20 +393,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
case I915_TILING_Y: case I915_TILING_Y:
/* FIXME: Is this true? */ /* FIXME: Is this true? */
DRM_ERROR("Y tiled not allowed for scan out buffers\n"); DRM_ERROR("Y tiled not allowed for scan out buffers\n");
return; return -EINVAL;
default: default:
BUG(); BUG();
} }
if (i915_gem_object_pin(intel_fb->obj, alignment)) mutex_lock(&dev->struct_mutex);
return; ret = i915_gem_object_pin(intel_fb->obj, alignment);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
if (ret != 0) {
Start = obj_priv->gtt_offset; i915_gem_object_unpin(intel_fb->obj);
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); mutex_unlock(&dev->struct_mutex);
return ret;
I915_WRITE(dspstride, crtc->fb->pitch); }
dspcntr = I915_READ(dspcntr_reg); dspcntr = I915_READ(dspcntr_reg);
/* Mask out pixel format bits in case we change it */ /* Mask out pixel format bits in case we change it */
@ -417,11 +431,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
break; break;
default: default:
DRM_ERROR("Unknown color depth\n"); DRM_ERROR("Unknown color depth\n");
return; i915_gem_object_unpin(intel_fb->obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
} }
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(dspcntr_reg, dspcntr);
Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) { if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset); I915_WRITE(dspbase, Offset);
I915_READ(dspbase); I915_READ(dspbase);
@ -438,27 +458,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
intel_fb = to_intel_framebuffer(old_fb); intel_fb = to_intel_framebuffer(old_fb);
i915_gem_object_unpin(intel_fb->obj); i915_gem_object_unpin(intel_fb->obj);
} }
mutex_unlock(&dev->struct_mutex);
if (!dev->primary->master) if (!dev->primary->master)
return; return 0;
master_priv = dev->primary->master->driver_priv; master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv) if (!master_priv->sarea_priv)
return; return 0;
switch (pipe) { if (pipe) {
case 0:
master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y;
break;
case 1:
master_priv->sarea_priv->pipeB_x = x; master_priv->sarea_priv->pipeB_x = x;
master_priv->sarea_priv->pipeB_y = y; master_priv->sarea_priv->pipeB_y = y;
break; } else {
default: master_priv->sarea_priv->pipeA_x = x;
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); master_priv->sarea_priv->pipeA_y = y;
break;
} }
return 0;
} }
@ -706,11 +723,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
return 1; return 1;
} }
static void intel_crtc_mode_set(struct drm_crtc *crtc, static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, struct drm_display_mode *adjusted_mode,
int x, int y, int x, int y,
struct drm_framebuffer *old_fb) struct drm_framebuffer *old_fb)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
@ -737,6 +754,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
bool is_crt = false, is_lvds = false, is_tv = false; bool is_crt = false, is_lvds = false, is_tv = false;
struct drm_mode_config *mode_config = &dev->mode_config; struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector; struct drm_connector *connector;
int ret;
drm_vblank_pre_modeset(dev, pipe); drm_vblank_pre_modeset(dev, pipe);
@ -777,7 +795,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock); ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
if (!ok) { if (!ok) {
DRM_ERROR("Couldn't find PLL settings for mode!\n"); DRM_ERROR("Couldn't find PLL settings for mode!\n");
return; return -EINVAL;
} }
fp = clock.n << 16 | clock.m1 << 8 | clock.m2; fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
@ -948,9 +966,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(dspcntr_reg, dspcntr); I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */ /* Flush the plane changes */
intel_pipe_set_base(crtc, x, y, old_fb); ret = intel_pipe_set_base(crtc, x, y, old_fb);
if (ret != 0)
return ret;
drm_vblank_post_modeset(dev, pipe); drm_vblank_post_modeset(dev, pipe);
return 0;
} }
/** Loads the palette/gamma unit for the CRTC with the prepared values */ /** Loads the palette/gamma unit for the CRTC with the prepared values */

View File

@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs {
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode); struct drm_display_mode *adjusted_mode);
/* Actually set the mode */ /* Actually set the mode */
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y, struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
/* Move the crtc on the current fb to the given position *optional* */ /* Move the crtc on the current fb to the given position *optional* */
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb); struct drm_framebuffer *old_fb);
}; };
struct drm_encoder_helper_funcs { struct drm_encoder_helper_funcs {