[Intel-gfx] [PATCH 3/4] drm/i915: Bail if plane/crtc init fails

Daniel Vetter daniel at ffwll.ch
Thu Oct 27 07:03:30 UTC 2016


On Tue, Oct 25, 2016 at 06:58:02PM +0300, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> Due to the plane->index not getting readjusted in drm_plane_cleanup(),
> we can't continue initialization of some plane/crtc init fails.
> Well, we sort of could I suppose if we left all initialized planes on
> the list, but that would expose those planes to userspace as well.
> 
> But for crtcs the situation is even worse since we assume that
> pipe==crtc index occasionally, so we can't really deal with a partially
> initialize set of crtcs.
> 
> So seems safest to just abort the entire thing if anything goes wrong.
> All the failure paths here are kmalloc()s anyway, so it seems unlikely
> we'd get very far if these start failing.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

Some bikeshedding in this patch, but I like it. For patches 1-3:

Reviewed-by: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.c      |   4 +-
>  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
>  drivers/gpu/drm/i915/intel_display.c | 101 ++++++++++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_drv.h     |   3 +-
>  drivers/gpu/drm/i915/intel_sprite.c  |   8 +--
>  5 files changed, 75 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index af3559d34328..0e393b5a988a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -592,7 +592,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  
>  	/* Important: The output setup functions called by modeset_init need
>  	 * working irqs for e.g. gmbus and dp aux transfers. */
> -	intel_modeset_init(dev);
> +	ret = intel_modeset_init(dev);
> +	if (ret)
> +		goto cleanup_irq;
>  
>  	intel_guc_init(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 7a621c74254e..a9308aeb2f1f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -3700,7 +3700,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv);
>  
>  /* modesetting */
>  extern void intel_modeset_init_hw(struct drm_device *dev);
> -extern void intel_modeset_init(struct drm_device *dev);
> +extern int intel_modeset_init(struct drm_device *dev);
>  extern void intel_modeset_gem_init(struct drm_device *dev);
>  extern void intel_modeset_cleanup(struct drm_device *dev);
>  extern int intel_connector_register(struct drm_connector *);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 244a0f59d8f7..d5a49d12dc88 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14975,9 +14975,6 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
>   */
>  void intel_plane_destroy(struct drm_plane *plane)
>  {
> -	if (!plane)
> -		return;
> -
>  	drm_plane_cleanup(plane);
>  	kfree(to_intel_plane(plane));
>  }
> @@ -14991,11 +14988,10 @@ const struct drm_plane_funcs intel_plane_funcs = {
>  	.atomic_set_property = intel_plane_atomic_set_property,
>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>  	.atomic_destroy_state = intel_plane_destroy_state,
> -
>  };
>  
> -static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
> -						    int pipe)
> +static struct intel_plane *
> +intel_primary_plane_create(struct drm_device *dev, enum pipe pipe)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_plane *primary = NULL;
> @@ -15006,12 +15002,17 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
>  	int ret;
>  
>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> -	if (!primary)
> +	if (!primary) {
> +		ret = -ENOMEM;
>  		goto fail;
> +	}
>  
>  	state = intel_create_plane_state(&primary->base);
> -	if (!state)
> +	if (!state) {
> +		ret = -ENOMEM;
>  		goto fail;
> +	}
> +
>  	primary->base.state = &state->base;
>  
>  	primary->can_scale = false;
> @@ -15092,13 +15093,13 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
>  
>  	drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
>  
> -	return &primary->base;
> +	return primary;
>  
>  fail:
>  	kfree(state);
>  	kfree(primary);
>  
> -	return NULL;
> +	return ERR_PTR(ret);
>  }
>  
>  static int
> @@ -15194,8 +15195,8 @@ intel_update_cursor_plane(struct drm_plane *plane,
>  	intel_crtc_update_cursor(crtc, state);
>  }
>  
> -static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
> -						   int pipe)
> +static struct intel_plane *
> +intel_cursor_plane_create(struct drm_device *dev, enum pipe pipe)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_plane *cursor = NULL;
> @@ -15203,12 +15204,17 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
>  	int ret;
>  
>  	cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
> -	if (!cursor)
> +	if (!cursor) {
> +		ret = -ENOMEM;
>  		goto fail;
> +	}
>  
>  	state = intel_create_plane_state(&cursor->base);
> -	if (!state)
> +	if (!state) {
> +		ret = -ENOMEM;
>  		goto fail;
> +	}
> +
>  	cursor->base.state = &state->base;
>  
>  	cursor->can_scale = false;
> @@ -15240,13 +15246,13 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
>  
>  	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
>  
> -	return &cursor->base;
> +	return cursor;
>  
>  fail:
>  	kfree(state);
>  	kfree(cursor);
>  
> -	return NULL;
> +	return ERR_PTR(ret);
>  }
>  
>  static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
> @@ -15265,22 +15271,24 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr
>  	scaler_state->scaler_id = -1;
>  }
>  
> -static void intel_crtc_init(struct drm_device *dev, int pipe)
> +static int intel_crtc_init(struct drm_device *dev, enum pipe pipe)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_crtc *intel_crtc;
>  	struct intel_crtc_state *crtc_state = NULL;
> -	struct drm_plane *primary = NULL;
> -	struct drm_plane *cursor = NULL;
> +	struct intel_plane *primary = NULL;
> +	struct intel_plane *cursor = NULL;
>  	int sprite, ret;
>  
>  	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
> -	if (intel_crtc == NULL)
> -		return;
> +	if (!intel_crtc)
> +		return -ENOMEM;
>  
>  	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
> -	if (!crtc_state)
> +	if (!crtc_state) {
> +		ret = -ENOMEM;
>  		goto fail;
> +	}
>  	intel_crtc->config = crtc_state;
>  	intel_crtc->base.state = &crtc_state->base;
>  	crtc_state->base.crtc = &intel_crtc->base;
> @@ -15296,22 +15304,30 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  	}
>  
>  	primary = intel_primary_plane_create(dev, pipe);
> -	if (!primary)
> +	if (IS_ERR(primary)) {
> +		ret = PTR_ERR(primary);
>  		goto fail;
> +	}
>  
>  	for_each_sprite(dev_priv, pipe, sprite) {
> -		ret = intel_plane_init(dev, pipe, sprite);
> -		if (ret)
> -			DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
> -				      pipe_name(pipe), sprite_name(pipe, sprite), ret);
> +		struct intel_plane *plane;
> +
> +		plane = intel_sprite_plane_create(dev, pipe, sprite);
> +		if (!plane) {
> +			ret = PTR_ERR(plane);
> +			goto fail;
> +		}
>  	}
>  
>  	cursor = intel_cursor_plane_create(dev, pipe);
> -	if (!cursor)
> +	if (!cursor) {
> +		ret = PTR_ERR(cursor);
>  		goto fail;
> +	}
>  
> -	ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
> -					cursor, &intel_crtc_funcs,
> +	ret = drm_crtc_init_with_planes(dev, &intel_crtc->base,
> +					&primary->base, &cursor->base,
> +					&intel_crtc_funcs,
>  					"pipe %c", pipe_name(pipe));
>  	if (ret)
>  		goto fail;
> @@ -15343,13 +15359,18 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  	intel_color_init(&intel_crtc->base);
>  
>  	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
> -	return;
> +
> +	return 0;
>  
>  fail:
> -	intel_plane_destroy(primary);
> -	intel_plane_destroy(cursor);
> +	/*
> +	 * drm_mode_config_cleanup() will free up any
> +	 * crtcs/planes already initialized.
> +	 */
>  	kfree(crtc_state);
>  	kfree(intel_crtc);
> +
> +	return ret;
>  }
>  
>  enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
> @@ -16426,7 +16447,7 @@ static void sanitize_watermarks(struct drm_device *dev)
>  	drm_modeset_acquire_fini(&ctx);
>  }
>  
> -void intel_modeset_init(struct drm_device *dev)
> +int intel_modeset_init(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct i915_ggtt *ggtt = &dev_priv->ggtt;
> @@ -16450,7 +16471,7 @@ void intel_modeset_init(struct drm_device *dev)
>  	intel_init_pm(dev);
>  
>  	if (INTEL_INFO(dev)->num_pipes == 0)
> -		return;
> +		return 0;
>  
>  	/*
>  	 * There may be no VBT; and if the BIOS enabled SSC we can
> @@ -16499,7 +16520,13 @@ void intel_modeset_init(struct drm_device *dev)
>  		      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
>  
>  	for_each_pipe(dev_priv, pipe) {
> -		intel_crtc_init(dev, pipe);
> +		int ret;
> +
> +		ret = intel_crtc_init(dev, pipe);
> +		if (ret) {
> +			drm_mode_config_cleanup(dev);
> +			return ret;
> +		}
>  	}
>  
>  	intel_update_czclk(dev_priv);
> @@ -16547,6 +16574,8 @@ void intel_modeset_init(struct drm_device *dev)
>  	 * since the watermark calculation done here will use pstate->fb.
>  	 */
>  	sanitize_watermarks(dev);
> +
> +	return 0;
>  }
>  
>  static void intel_enable_pipe_a(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 7dda79df55d0..4fd7d74fd6dc 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1779,7 +1779,8 @@ bool intel_sdvo_init(struct drm_device *dev,
>  /* intel_sprite.c */
>  int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
>  			     int usecs);
> -int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
> +struct intel_plane *intel_sprite_plane_create(struct drm_device *dev,
> +					      enum pipe pipe, int plane);
>  int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
>  			      struct drm_file *file_priv);
>  void intel_pipe_update_start(struct intel_crtc *crtc);
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index ae1e3d47951b..41ae7f562eec 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -1042,8 +1042,8 @@ static uint32_t skl_plane_formats[] = {
>  	DRM_FORMAT_VYUY,
>  };
>  
> -int
> -intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
> +struct intel_plane *
> +intel_sprite_plane_create(struct drm_device *dev, enum pipe pipe, int plane)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_plane *intel_plane = NULL;
> @@ -1160,11 +1160,11 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
>  
>  	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
>  
> -	return 0;
> +	return intel_plane;
>  
>  fail:
>  	kfree(state);
>  	kfree(intel_plane);
>  
> -	return ret;
> +	return ERR_PTR(ret);
>  }
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the Intel-gfx mailing list