Skip to content

Commit

Permalink
drm: Propagate failure from setting crtc base.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Wilson authored and Dave Airlie committed Feb 20, 2009
1 parent e62fb64 commit 5c3b82e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 40 deletions.
15 changes: 11 additions & 4 deletions drivers/gpu/drm/drm_crtc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (drm_mode_equal(&saved_mode, &crtc->mode)) {
if (saved_x != crtc->x || saved_y != crtc->y ||
depth_changed || bpp_changed) {
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb);
ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb);
goto done;
}
}
Expand Down Expand Up @@ -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
* 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) {

Expand Down Expand Up @@ -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,
set->x, set->y,
old_fb)) {
DRM_ERROR("failed to set mode on crtc %p\n",
set->crtc);
ret = -EINVAL;
goto fail_set_mode;
}
Expand All @@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
old_fb = set->crtc->fb;
if (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);
Expand Down
84 changes: 53 additions & 31 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ intel_wait_for_vblank(struct drm_device *dev)
udelay(20000);
}

static void
static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
Expand All @@ -361,11 +361,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr, alignment;
int ret;

/* no fb bound */
if (!crtc->fb) {
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);
Expand All @@ -383,20 +393,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
case I915_TILING_Y:
/* FIXME: Is this true? */
DRM_ERROR("Y tiled not allowed for scan out buffers\n");
return;
return -EINVAL;
default:
BUG();
}

if (i915_gem_object_pin(intel_fb->obj, alignment))
return;

i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);

Start = obj_priv->gtt_offset;
Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
mutex_lock(&dev->struct_mutex);
ret = i915_gem_object_pin(intel_fb->obj, alignment);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
return ret;
}

I915_WRITE(dspstride, crtc->fb->pitch);
ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
if (ret != 0) {
i915_gem_object_unpin(intel_fb->obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}

dspcntr = I915_READ(dspcntr_reg);
/* Mask out pixel format bits in case we change it */
Expand All @@ -417,11 +431,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
break;
default:
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);

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);
I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset);
I915_READ(dspbase);
Expand All @@ -438,27 +458,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
intel_fb = to_intel_framebuffer(old_fb);
i915_gem_object_unpin(intel_fb->obj);
}
mutex_unlock(&dev->struct_mutex);

if (!dev->primary->master)
return;
return 0;

master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv)
return;
return 0;

switch (pipe) {
case 0:
master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y;
break;
case 1:
if (pipe) {
master_priv->sarea_priv->pipeB_x = x;
master_priv->sarea_priv->pipeB_y = y;
break;
default:
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
break;
} else {
master_priv->sarea_priv->pipeA_x = x;
master_priv->sarea_priv->pipeA_y = y;
}

return 0;
}


Expand Down Expand Up @@ -706,11 +723,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
return 1;
}

static void intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb)
static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
Expand All @@ -737,6 +754,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
bool is_crt = false, is_lvds = false, is_tv = false;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
int ret;

drm_vblank_pre_modeset(dev, pipe);

Expand Down Expand Up @@ -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);
if (!ok) {
DRM_ERROR("Couldn't find PLL settings for mode!\n");
return;
return -EINVAL;
}

fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
Expand Down Expand Up @@ -948,9 +966,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(dspcntr_reg, dspcntr);

/* 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);

return 0;
}

/** Loads the palette/gamma unit for the CRTC with the prepared values */
Expand Down
10 changes: 5 additions & 5 deletions include/drm/drm_crtc_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs {
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
/* Actually set the mode */
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb);
int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, int x, int y,
struct drm_framebuffer *old_fb);

/* Move the crtc on the current fb to the given position *optional* */
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb);
int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb);
};

struct drm_encoder_helper_funcs {
Expand Down

0 comments on commit 5c3b82e

Please sign in to comment.