[Intel-gfx] [PATCH 05/23] drm/i915: Allocate a drm_atomic_state for the legacy modeset code
Daniel Vetter
daniel at ffwll.ch
Wed Mar 4 07:33:17 PST 2015
On Tue, Mar 03, 2015 at 03:21:59PM +0200, Ander Conselvan de Oliveira wrote:
> For the atomic conversion, the mode set paths need to be changed to rely
> on an atomic state instead of using the staged config. By using an
> atomic state for the legacy code, we will be able to convert the code
> base in small chunks.
>
> Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
Two small comments below.
-Daniel
> ---
> drivers/gpu/drm/i915/intel_display.c | 118 +++++++++++++++++++++++++++--------
> 1 file changed, 91 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 798de7b..97d4df5 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -37,6 +37,7 @@
> #include <drm/i915_drm.h>
> #include "i915_drv.h"
> #include "i915_trace.h"
> +#include <drm/drm_atomic.h>
> #include <drm/drm_atomic_helper.h>
> #include <drm/drm_dp_helper.h>
> #include <drm/drm_crtc_helper.h>
> @@ -10290,10 +10291,22 @@ static bool check_digital_port_conflicts(struct drm_device *dev)
> return true;
> }
>
> -static struct intel_crtc_state *
> +static void
> +clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
> +{
> + struct drm_crtc_state tmp_state;
> +
> + /* Clear only the intel specific part of the crtc state */
> + tmp_state = crtc_state->base;
> + memset(crtc_state, 0, sizeof *crtc_state);
> + crtc_state->base = tmp_state;
> +}
I guess this is to clear out state which we want to recompute, and our
compute_config code assumes that it's always kzalloc'ed a new config?
I think this should be part of the crtc duplicate_state callback to make
sure we're doing this consistently.
> +
> +static int
> intel_modeset_pipe_config(struct drm_crtc *crtc,
> struct drm_framebuffer *fb,
> - struct drm_display_mode *mode)
> + struct drm_display_mode *mode,
> + struct drm_atomic_state *state)
> {
> struct drm_device *dev = crtc->dev;
> struct intel_encoder *encoder;
> @@ -10303,17 +10316,19 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
>
> if (!check_encoder_cloning(to_intel_crtc(crtc))) {
> DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
> - return ERR_PTR(-EINVAL);
> + return -EINVAL;
> }
>
> if (!check_digital_port_conflicts(dev)) {
> DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
> - return ERR_PTR(-EINVAL);
> + return -EINVAL;
> }
>
> - pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
> - if (!pipe_config)
> - return ERR_PTR(-ENOMEM);
> + pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
> + if (IS_ERR(pipe_config))
> + return PTR_ERR(pipe_config);
> +
> + clear_intel_crtc_state(pipe_config);
>
> pipe_config->base.crtc = crtc;
> drm_mode_copy(&pipe_config->base.adjusted_mode, mode);
> @@ -10408,10 +10423,9 @@ encoder_retry:
> DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
> plane_bpp, pipe_config->pipe_bpp, pipe_config->dither);
>
> - return pipe_config;
> + return 0;
> fail:
> - kfree(pipe_config);
> - return ERR_PTR(ret);
> + return ret;
> }
>
> /* Computes which crtcs are affected and sets the relevant bits in the mask. For
> @@ -11089,17 +11103,19 @@ static struct intel_crtc_state *
> intel_modeset_compute_config(struct drm_crtc *crtc,
> struct drm_display_mode *mode,
> struct drm_framebuffer *fb,
> + struct drm_atomic_state *state,
> unsigned *modeset_pipes,
> unsigned *prepare_pipes,
> unsigned *disable_pipes)
> {
> struct intel_crtc_state *pipe_config = NULL;
> + int ret = 0;
>
> intel_modeset_affected_pipes(crtc, modeset_pipes,
> prepare_pipes, disable_pipes);
>
> if ((*modeset_pipes) == 0)
> - goto out;
> + return NULL;
>
> /*
> * Note this needs changes when we start tracking multiple modes
> @@ -11107,14 +11123,17 @@ intel_modeset_compute_config(struct drm_crtc *crtc,
> * (i.e. one pipe_config for each crtc) rather than just the one
> * for this crtc.
> */
> - pipe_config = intel_modeset_pipe_config(crtc, fb, mode);
> - if (IS_ERR(pipe_config)) {
> - goto out;
> - }
> + ret = intel_modeset_pipe_config(crtc, fb, mode, state);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
> + if (IS_ERR(pipe_config))
> + return pipe_config;
> +
> intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
> "[modeset]");
>
> -out:
> return pipe_config;
> }
>
> @@ -11159,6 +11178,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
> struct drm_device *dev = crtc->dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_display_mode *saved_mode;
> + struct intel_crtc_state *crtc_state_copy = NULL;
> struct intel_crtc *intel_crtc;
> int ret = 0;
>
> @@ -11166,6 +11186,12 @@ static int __intel_set_mode(struct drm_crtc *crtc,
> if (!saved_mode)
> return -ENOMEM;
>
> + crtc_state_copy = kmalloc(sizeof(*crtc_state_copy), GFP_KERNEL);
> + if (!crtc_state_copy) {
> + ret = -ENOMEM;
> + goto done;
> + }
> +
> *saved_mode = crtc->mode;
>
> if (modeset_pipes)
> @@ -11252,6 +11278,19 @@ done:
> if (ret && crtc->state->enable)
> crtc->mode = *saved_mode;
>
> + if (ret == 0 && pipe_config) {
> + struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> + /* The pipe_config will be freed with the atomic state, so
> + * make a copy. */
> + memcpy(crtc_state_copy, intel_crtc->config,
> + sizeof *crtc_state_copy);
> + intel_crtc->config = intel_crtc->new_config = crtc_state_copy;
> + intel_crtc->base.state = &crtc_state_copy->base;
> + } else {
> + kfree(crtc_state_copy);
> + }
> +
> kfree(saved_mode);
> return ret;
> }
> @@ -11279,20 +11318,37 @@ static int intel_set_mode(struct drm_crtc *crtc,
> struct drm_display_mode *mode,
> int x, int y, struct drm_framebuffer *fb)
> {
> + struct drm_device *dev = crtc->dev;
> + struct drm_atomic_state *state;
> struct intel_crtc_state *pipe_config;
> unsigned modeset_pipes, prepare_pipes, disable_pipes;
> + int ret = 0;
> +
> + state = drm_atomic_state_alloc(dev);
> + if (!state)
> + return -ENOMEM;
> +
> + state->acquire_ctx = dev->mode_config.acquire_ctx;
>
> - pipe_config = intel_modeset_compute_config(crtc, mode, fb,
> + pipe_config = intel_modeset_compute_config(crtc, mode, fb, state,
> &modeset_pipes,
> &prepare_pipes,
> &disable_pipes);
>
> - if (IS_ERR(pipe_config))
> - return PTR_ERR(pipe_config);
> + if (IS_ERR(pipe_config)) {
> + ret = PTR_ERR(pipe_config);
> + goto out;
> + }
> +
> + ret = intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config,
> + modeset_pipes, prepare_pipes,
> + disable_pipes);
> + if (ret)
> + goto out;
>
> - return intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config,
> - modeset_pipes, prepare_pipes,
> - disable_pipes);
> +out:
> + drm_atomic_state_free(state);
> + return ret;
> }
>
> void intel_crtc_restore_mode(struct drm_crtc *crtc)
> @@ -11622,6 +11678,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
> {
> struct drm_device *dev;
> struct drm_mode_set save_set;
> + struct drm_atomic_state *state = NULL;
> struct intel_set_config *config;
> struct intel_crtc_state *pipe_config;
> unsigned modeset_pipes, prepare_pipes, disable_pipes;
> @@ -11666,12 +11723,20 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
> * such cases. */
> intel_set_config_compute_mode_changes(set, config);
>
> + state = drm_atomic_state_alloc(dev);
> + if (!state) {
> + ret = -ENOMEM;
> + goto out_config;
> + }
> +
> + state->acquire_ctx = dev->mode_config.acquire_ctx;
> +
> ret = intel_modeset_stage_output_state(dev, set, config);
> if (ret)
> goto fail;
>
> pipe_config = intel_modeset_compute_config(set->crtc, set->mode,
> - set->fb,
> + set->fb, state,
> &modeset_pipes,
> &prepare_pipes,
> &disable_pipes);
> @@ -11691,10 +11756,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
> */
> }
>
> - /* set_mode will free it in the mode_changed case */
> - if (!config->mode_changed)
> - kfree(pipe_config);
> -
> intel_update_pipe_size(to_intel_crtc(set->crtc));
>
> if (config->mode_changed) {
> @@ -11757,6 +11818,9 @@ fail:
> }
>
> out_config:
> + if (state)
> + drm_atomic_state_free(state);
Right above this we also call set_mode again, which also grabs a global
state. Nesting seems tricky, so I thnk you should free up the atomic state
before we try the failure code paths to restore the old state.
> +
> intel_set_config_free(config);
> return ret;
> }
> --
> 2.1.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
More information about the Intel-gfx
mailing list