[Intel-gfx] [PATCH 07/10] drm/i915/display: add intel_display_reset.[ch]
Gustavo Sousa
gustavo.sousa at intel.com
Thu Apr 13 16:59:05 UTC 2023
Quoting Jani Nikula (2023-04-13 06:47:33)
> Split out the display reset functionality to a separate file to
> declutter intel_display.c. Rename the functions accordingly. The minor
> downside is having to expose __intel_display_resume().
>
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>
Reviewed-by: Gustavo Sousa <gustavo.sousa at intel.com>
> ---
> drivers/gpu/drm/i915/Makefile | 1 +
> drivers/gpu/drm/i915/display/intel_display.c | 123 +---------------
> drivers/gpu/drm/i915/display/intel_display.h | 8 +-
> .../drm/i915/display/intel_display_reset.c | 135 ++++++++++++++++++
> .../drm/i915/display/intel_display_reset.h | 14 ++
> drivers/gpu/drm/i915/gt/intel_reset.c | 6 +-
> 6 files changed, 160 insertions(+), 127 deletions(-)
> create mode 100644 drivers/gpu/drm/i915/display/intel_display_reset.c
> create mode 100644 drivers/gpu/drm/i915/display/intel_display_reset.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 91f0c214ef28..39e22cf85e55 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -241,6 +241,7 @@ i915-y += \
> display/intel_display_power.o \
> display/intel_display_power_map.o \
> display/intel_display_power_well.o \
> + display/intel_display_reset.o \
> display/intel_display_rps.o \
> display/intel_dmc.o \
> display/intel_dpio_phy.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index f425e5ed155b..e89e9473a744 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -693,7 +693,7 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
> return y;
> }
>
> -static int
> +int
> __intel_display_resume(struct drm_i915_private *i915,
> struct drm_atomic_state *state,
> struct drm_modeset_acquire_ctx *ctx)
> @@ -733,127 +733,6 @@ __intel_display_resume(struct drm_i915_private *i915,
> return ret;
> }
>
> -static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
> -{
> - return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
> - intel_has_gpu_reset(to_gt(dev_priv)));
> -}
> -
> -void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
> -{
> - struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx;
> - struct drm_atomic_state *state;
> - int ret;
> -
> - if (!HAS_DISPLAY(dev_priv))
> - return;
> -
> - /* reset doesn't touch the display */
> - if (!dev_priv->params.force_reset_modeset_test &&
> - !gpu_reset_clobbers_display(dev_priv))
> - return;
> -
> - /* We have a modeset vs reset deadlock, defensively unbreak it. */
> - set_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags);
> - smp_mb__after_atomic();
> - wake_up_bit(&to_gt(dev_priv)->reset.flags, I915_RESET_MODESET);
> -
> - if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
> - drm_dbg_kms(&dev_priv->drm,
> - "Modeset potentially stuck, unbreaking through wedging\n");
> - intel_gt_set_wedged(to_gt(dev_priv));
> - }
> -
> - /*
> - * Need mode_config.mutex so that we don't
> - * trample ongoing ->detect() and whatnot.
> - */
> - mutex_lock(&dev_priv->drm.mode_config.mutex);
> - drm_modeset_acquire_init(ctx, 0);
> - while (1) {
> - ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx);
> - if (ret != -EDEADLK)
> - break;
> -
> - drm_modeset_backoff(ctx);
> - }
> - /*
> - * Disabling the crtcs gracefully seems nicer. Also the
> - * g33 docs say we should at least disable all the planes.
> - */
> - state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx);
> - if (IS_ERR(state)) {
> - ret = PTR_ERR(state);
> - drm_err(&dev_priv->drm, "Duplicating state failed with %i\n",
> - ret);
> - return;
> - }
> -
> - ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx);
> - if (ret) {
> - drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
> - ret);
> - drm_atomic_state_put(state);
> - return;
> - }
> -
> - dev_priv->display.restore.modeset_state = state;
> - state->acquire_ctx = ctx;
> -}
> -
> -void intel_display_finish_reset(struct drm_i915_private *i915)
> -{
> - struct drm_modeset_acquire_ctx *ctx = &i915->display.restore.reset_ctx;
> - struct drm_atomic_state *state;
> - int ret;
> -
> - if (!HAS_DISPLAY(i915))
> - return;
> -
> - /* reset doesn't touch the display */
> - if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags))
> - return;
> -
> - state = fetch_and_zero(&i915->display.restore.modeset_state);
> - if (!state)
> - goto unlock;
> -
> - /* reset doesn't touch the display */
> - if (!gpu_reset_clobbers_display(i915)) {
> - /* for testing only restore the display */
> - ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
> - if (ret) {
> - drm_WARN_ON(&i915->drm, ret == -EDEADLK);
> - drm_err(&i915->drm,
> - "Restoring old state failed with %i\n", ret);
> - }
> - } else {
> - /*
> - * The display has been reset as well,
> - * so need a full re-initialization.
> - */
> - intel_pps_unlock_regs_wa(i915);
> - intel_display_driver_init_hw(i915);
> - intel_clock_gating_init(i915);
> - intel_hpd_init(i915);
> -
> - ret = __intel_display_resume(i915, state, ctx);
> - if (ret)
> - drm_err(&i915->drm,
> - "Restoring old state failed with %i\n", ret);
> -
> - intel_hpd_poll_disable(i915);
> - }
> -
> - drm_atomic_state_put(state);
> -unlock:
> - drm_modeset_drop_locks(ctx);
> - drm_modeset_acquire_fini(ctx);
> - mutex_unlock(&i915->drm.mode_config.mutex);
> -
> - clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags);
> -}
> -
> static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
> {
> struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index f82987fbc94a..e5bf8ef8e06b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -468,8 +468,6 @@ intel_framebuffer_create(struct drm_i915_gem_object *obj,
>
> bool intel_fuzzy_clock_check(int clock1, int clock2);
>
> -void intel_display_prepare_reset(struct drm_i915_private *dev_priv);
> -void intel_display_finish_reset(struct drm_i915_private *dev_priv);
> void intel_zero_m_n(struct intel_link_m_n *m_n);
> void intel_set_m_n(struct drm_i915_private *i915,
> const struct intel_link_m_n *m_n,
> @@ -545,6 +543,12 @@ int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *_state);
>
> void intel_hpd_poll_fini(struct drm_i915_private *i915);
>
> +/* interface for intel_display_reset.c */
> +int
> +__intel_display_resume(struct drm_i915_private *i915,
> + struct drm_atomic_state *state,
> + struct drm_modeset_acquire_ctx *ctx);
> +
> /* modesetting asserts */
> void assert_transcoder(struct drm_i915_private *dev_priv,
> enum transcoder cpu_transcoder, bool state);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c
> new file mode 100644
> index 000000000000..166aa0cab1fc
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c
> @@ -0,0 +1,135 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +
> +#include "i915_drv.h"
> +#include "intel_clock_gating.h"
> +#include "intel_display_driver.h"
> +#include "intel_display_reset.h"
> +#include "intel_display_types.h"
> +#include "intel_hotplug.h"
> +#include "intel_pps.h"
> +
> +static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
> +{
> + return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
> + intel_has_gpu_reset(to_gt(dev_priv)));
> +}
> +
> +void intel_display_reset_prepare(struct drm_i915_private *dev_priv)
> +{
> + struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx;
> + struct drm_atomic_state *state;
> + int ret;
> +
> + if (!HAS_DISPLAY(dev_priv))
> + return;
> +
> + /* reset doesn't touch the display */
> + if (!dev_priv->params.force_reset_modeset_test &&
> + !gpu_reset_clobbers_display(dev_priv))
> + return;
> +
> + /* We have a modeset vs reset deadlock, defensively unbreak it. */
> + set_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags);
> + smp_mb__after_atomic();
> + wake_up_bit(&to_gt(dev_priv)->reset.flags, I915_RESET_MODESET);
> +
> + if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
> + drm_dbg_kms(&dev_priv->drm,
> + "Modeset potentially stuck, unbreaking through wedging\n");
> + intel_gt_set_wedged(to_gt(dev_priv));
> + }
> +
> + /*
> + * Need mode_config.mutex so that we don't
> + * trample ongoing ->detect() and whatnot.
> + */
> + mutex_lock(&dev_priv->drm.mode_config.mutex);
> + drm_modeset_acquire_init(ctx, 0);
> + while (1) {
> + ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx);
> + if (ret != -EDEADLK)
> + break;
> +
> + drm_modeset_backoff(ctx);
> + }
> + /*
> + * Disabling the crtcs gracefully seems nicer. Also the
> + * g33 docs say we should at least disable all the planes.
> + */
> + state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx);
> + if (IS_ERR(state)) {
> + ret = PTR_ERR(state);
> + drm_err(&dev_priv->drm, "Duplicating state failed with %i\n",
> + ret);
> + return;
> + }
> +
> + ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx);
> + if (ret) {
> + drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
> + ret);
> + drm_atomic_state_put(state);
> + return;
> + }
> +
> + dev_priv->display.restore.modeset_state = state;
> + state->acquire_ctx = ctx;
> +}
> +
> +void intel_display_reset_finish(struct drm_i915_private *i915)
> +{
> + struct drm_modeset_acquire_ctx *ctx = &i915->display.restore.reset_ctx;
> + struct drm_atomic_state *state;
> + int ret;
> +
> + if (!HAS_DISPLAY(i915))
> + return;
> +
> + /* reset doesn't touch the display */
> + if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags))
> + return;
> +
> + state = fetch_and_zero(&i915->display.restore.modeset_state);
> + if (!state)
> + goto unlock;
> +
> + /* reset doesn't touch the display */
> + if (!gpu_reset_clobbers_display(i915)) {
> + /* for testing only restore the display */
> + ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
> + if (ret) {
> + drm_WARN_ON(&i915->drm, ret == -EDEADLK);
> + drm_err(&i915->drm,
> + "Restoring old state failed with %i\n", ret);
> + }
> + } else {
> + /*
> + * The display has been reset as well,
> + * so need a full re-initialization.
> + */
> + intel_pps_unlock_regs_wa(i915);
> + intel_display_driver_init_hw(i915);
> + intel_clock_gating_init(i915);
> + intel_hpd_init(i915);
> +
> + ret = __intel_display_resume(i915, state, ctx);
> + if (ret)
> + drm_err(&i915->drm,
> + "Restoring old state failed with %i\n", ret);
> +
> + intel_hpd_poll_disable(i915);
> + }
> +
> + drm_atomic_state_put(state);
> +unlock:
> + drm_modeset_drop_locks(ctx);
> + drm_modeset_acquire_fini(ctx);
> + mutex_unlock(&i915->drm.mode_config.mutex);
> +
> + clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.h b/drivers/gpu/drm/i915/display/intel_display_reset.h
> new file mode 100644
> index 000000000000..f06d0d35b86b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_display_reset.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2023 Intel Corporation
> + */
> +
> +#ifndef __INTEL_RESET_H__
> +#define __INTEL_RESET_H__
> +
> +struct drm_i915_private;
> +
> +void intel_display_reset_prepare(struct drm_i915_private *i915);
> +void intel_display_reset_finish(struct drm_i915_private *i915);
> +
> +#endif /* __INTEL_RESET_H__ */
> diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
> index 797ea8340467..6194212e8650 100644
> --- a/drivers/gpu/drm/i915/gt/intel_reset.c
> +++ b/drivers/gpu/drm/i915/gt/intel_reset.c
> @@ -7,7 +7,7 @@
> #include <linux/stop_machine.h>
> #include <linux/string_helpers.h>
>
> -#include "display/intel_display.h"
> +#include "display/intel_display_reset.h"
> #include "display/intel_overlay.h"
>
> #include "gem/i915_gem_context.h"
> @@ -1370,11 +1370,11 @@ static void intel_gt_reset_global(struct intel_gt *gt,
>
> /* Use a watchdog to ensure that our reset completes */
> intel_wedge_on_timeout(&w, gt, 60 * HZ) {
> - intel_display_prepare_reset(gt->i915);
> + intel_display_reset_prepare(gt->i915);
>
> intel_gt_reset(gt, engine_mask, reason);
>
> - intel_display_finish_reset(gt->i915);
> + intel_display_reset_finish(gt->i915);
> }
>
> if (!test_bit(I915_WEDGED, >->reset.flags))
> --
> 2.39.2
>
More information about the Intel-gfx
mailing list