From 59c6106e274dbafd9d25357585ae5ede4b6673dd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 14 Apr 2023 12:41:59 +0300 Subject: drm/i915/display: add intel_display_reset.[ch] 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(). Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/5e98e2fc5f0c09490e02d22250c8201342852288.1681465222.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_reset.c | 135 +++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_display_reset.c (limited to 'drivers/gpu/drm/i915/display/intel_display_reset.c') 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 + +#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); +} -- cgit v1.2.3 From cde4bd87863124fb6feee35b7f73552f5e75ea61 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 14 Apr 2023 12:42:01 +0300 Subject: drm/i915/display: rename intel_display_driver_suspend/resume functions Follow the usual naming conventions. Switch to i915 arguments and naming while at it. Reviewed-by: Gustavo Sousa Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/cdd4228337678609967ed176dcfc9690de5d490b.1681465222.git.jani.nikula@intel.com --- .../gpu/drm/i915/display/intel_display_driver.c | 24 ++++++++++------------ .../gpu/drm/i915/display/intel_display_driver.h | 11 +++++----- drivers/gpu/drm/i915/display/intel_display_reset.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 6 +++--- 4 files changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_display_reset.c') diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index eb03b0a87d5a..d20a279fdf51 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -471,29 +471,28 @@ void intel_display_driver_unregister(struct drm_i915_private *i915) * turn all crtc's off, but do not adjust state * This has to be paired with a call to intel_modeset_setup_hw_state. */ -int intel_display_suspend(struct drm_device *dev) +int intel_display_driver_suspend(struct drm_i915_private *i915) { - struct drm_i915_private *dev_priv = to_i915(dev); struct drm_atomic_state *state; int ret; - if (!HAS_DISPLAY(dev_priv)) + if (!HAS_DISPLAY(i915)) return 0; - state = drm_atomic_helper_suspend(dev); + state = drm_atomic_helper_suspend(&i915->drm); ret = PTR_ERR_OR_ZERO(state); if (ret) - drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n", + drm_err(&i915->drm, "Suspending crtc's failed with %i\n", ret); else - dev_priv->display.restore.modeset_state = state; + i915->display.restore.modeset_state = state; return ret; } int -__intel_display_resume(struct drm_i915_private *i915, - struct drm_atomic_state *state, - struct drm_modeset_acquire_ctx *ctx) +__intel_display_driver_resume(struct drm_i915_private *i915, + struct drm_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx) { struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; @@ -530,9 +529,8 @@ __intel_display_resume(struct drm_i915_private *i915, return ret; } -void intel_display_resume(struct drm_device *dev) +void intel_display_driver_resume(struct drm_i915_private *i915) { - struct drm_i915_private *i915 = to_i915(dev); struct drm_atomic_state *state = i915->display.restore.modeset_state; struct drm_modeset_acquire_ctx ctx; int ret; @@ -547,7 +545,7 @@ void intel_display_resume(struct drm_device *dev) drm_modeset_acquire_init(&ctx, 0); while (1) { - ret = drm_modeset_lock_all_ctx(dev, &ctx); + ret = drm_modeset_lock_all_ctx(&i915->drm, &ctx); if (ret != -EDEADLK) break; @@ -555,7 +553,7 @@ void intel_display_resume(struct drm_device *dev) } if (!ret) - ret = __intel_display_resume(i915, state, &ctx); + ret = __intel_display_driver_resume(i915, state, &ctx); skl_watermark_ipc_update(i915); drm_modeset_drop_locks(&ctx); diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.h b/drivers/gpu/drm/i915/display/intel_display_driver.h index 7b5ff4309dec..84e7977f265a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.h +++ b/drivers/gpu/drm/i915/display/intel_display_driver.h @@ -9,7 +9,6 @@ #include struct drm_atomic_state; -struct drm_device; struct drm_i915_private; struct drm_modeset_acquire_ctx; struct pci_dev; @@ -24,13 +23,13 @@ void intel_display_driver_remove(struct drm_i915_private *i915); void intel_display_driver_remove_noirq(struct drm_i915_private *i915); void intel_display_driver_remove_nogem(struct drm_i915_private *i915); void intel_display_driver_unregister(struct drm_i915_private *i915); -int intel_display_suspend(struct drm_device *dev); -void intel_display_resume(struct drm_device *dev); +int intel_display_driver_suspend(struct drm_i915_private *i915); +void intel_display_driver_resume(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); +int __intel_display_driver_resume(struct drm_i915_private *i915, + struct drm_atomic_state *state, + struct drm_modeset_acquire_ctx *ctx); #endif /* __INTEL_DISPLAY_DRIVER_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_reset.c b/drivers/gpu/drm/i915/display/intel_display_reset.c index 166aa0cab1fc..17178d5d7788 100644 --- a/drivers/gpu/drm/i915/display/intel_display_reset.c +++ b/drivers/gpu/drm/i915/display/intel_display_reset.c @@ -117,7 +117,7 @@ void intel_display_reset_finish(struct drm_i915_private *i915) intel_clock_gating_init(i915); intel_hpd_init(i915); - ret = __intel_display_resume(i915, state, ctx); + ret = __intel_display_driver_resume(i915, state, ctx); if (ret) drm_err(&i915->drm, "Restoring old state failed with %i\n", ret); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index d38ce3885c4d..d36e4b019cce 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1043,7 +1043,7 @@ static int i915_drm_prepare(struct drm_device *dev) intel_pxp_suspend_prepare(i915->pxp); /* - * NB intel_display_suspend() may issue new requests after we've + * NB intel_display_driver_suspend() may issue new requests after we've * ostensibly marked the GPU as ready-to-sleep here. We need to * split out that work and pull it forward so that after point, * the GPU is not woken again. @@ -1067,7 +1067,7 @@ static int i915_drm_suspend(struct drm_device *dev) pci_save_state(pdev); - intel_display_suspend(dev); + intel_display_driver_suspend(dev_priv); intel_dp_mst_suspend(dev_priv); @@ -1241,7 +1241,7 @@ static int i915_drm_resume(struct drm_device *dev) /* MST sideband requires HPD interrupts enabled */ intel_dp_mst_resume(dev_priv); - intel_display_resume(dev); + intel_display_driver_resume(dev_priv); intel_hpd_poll_disable(dev_priv); if (HAS_DISPLAY(dev_priv)) -- cgit v1.2.3