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:
		
							parent
							
								
									e62fb64e61
								
							
						
					
					
						commit
						5c3b82e2b2
					
				| @ -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; | ||||
| 		} | ||||
| 	} | ||||
| @ -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) { | ||||
| 
 | ||||
| @ -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; | ||||
| 			} | ||||
| @ -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); | ||||
|  | ||||
| @ -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) | ||||
| { | ||||
| @ -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); | ||||
| @ -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; | ||||
| 	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_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); | ||||
| 
 | ||||
| 	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 */ | ||||
| @ -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); | ||||
| @ -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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -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; | ||||
| @ -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); | ||||
| 
 | ||||
| @ -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; | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user