1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <drm/drm_atomic_helper.h> 7 8 #include "i915_drv.h" 9 #include "intel_clock_gating.h" 10 #include "intel_cx0_phy.h" 11 #include "intel_display_driver.h" 12 #include "intel_display_reset.h" 13 #include "intel_display_types.h" 14 #include "intel_hotplug.h" 15 #include "intel_pps.h" 16 17 static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv) 18 { 19 return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display && 20 intel_has_gpu_reset(to_gt(dev_priv))); 21 } 22 23 void intel_display_reset_prepare(struct drm_i915_private *dev_priv) 24 { 25 struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx; 26 struct drm_atomic_state *state; 27 int ret; 28 29 if (!HAS_DISPLAY(dev_priv)) 30 return; 31 32 /* reset doesn't touch the display */ 33 if (!dev_priv->display.params.force_reset_modeset_test && 34 !gpu_reset_clobbers_display(dev_priv)) 35 return; 36 37 /* We have a modeset vs reset deadlock, defensively unbreak it. */ 38 set_bit(I915_RESET_MODESET, &to_gt(dev_priv)->reset.flags); 39 smp_mb__after_atomic(); 40 wake_up_bit(&to_gt(dev_priv)->reset.flags, I915_RESET_MODESET); 41 42 if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) { 43 drm_dbg_kms(&dev_priv->drm, 44 "Modeset potentially stuck, unbreaking through wedging\n"); 45 intel_gt_set_wedged(to_gt(dev_priv)); 46 } 47 48 /* 49 * Need mode_config.mutex so that we don't 50 * trample ongoing ->detect() and whatnot. 51 */ 52 mutex_lock(&dev_priv->drm.mode_config.mutex); 53 drm_modeset_acquire_init(ctx, 0); 54 while (1) { 55 ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx); 56 if (ret != -EDEADLK) 57 break; 58 59 drm_modeset_backoff(ctx); 60 } 61 /* 62 * Disabling the crtcs gracefully seems nicer. Also the 63 * g33 docs say we should at least disable all the planes. 64 */ 65 state = drm_atomic_helper_duplicate_state(&dev_priv->drm, ctx); 66 if (IS_ERR(state)) { 67 ret = PTR_ERR(state); 68 drm_err(&dev_priv->drm, "Duplicating state failed with %i\n", 69 ret); 70 return; 71 } 72 73 ret = drm_atomic_helper_disable_all(&dev_priv->drm, ctx); 74 if (ret) { 75 drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n", 76 ret); 77 drm_atomic_state_put(state); 78 return; 79 } 80 81 dev_priv->display.restore.modeset_state = state; 82 state->acquire_ctx = ctx; 83 } 84 85 void intel_display_reset_finish(struct drm_i915_private *i915) 86 { 87 struct intel_display *display = &i915->display; 88 struct drm_modeset_acquire_ctx *ctx = &display->restore.reset_ctx; 89 struct drm_atomic_state *state; 90 int ret; 91 92 if (!HAS_DISPLAY(i915)) 93 return; 94 95 /* reset doesn't touch the display */ 96 if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags)) 97 return; 98 99 state = fetch_and_zero(&display->restore.modeset_state); 100 if (!state) 101 goto unlock; 102 103 /* reset doesn't touch the display */ 104 if (!gpu_reset_clobbers_display(i915)) { 105 /* for testing only restore the display */ 106 ret = drm_atomic_helper_commit_duplicated_state(state, ctx); 107 if (ret) { 108 drm_WARN_ON(&i915->drm, ret == -EDEADLK); 109 drm_err(&i915->drm, 110 "Restoring old state failed with %i\n", ret); 111 } 112 } else { 113 /* 114 * The display has been reset as well, 115 * so need a full re-initialization. 116 */ 117 intel_pps_unlock_regs_wa(display); 118 intel_display_driver_init_hw(display); 119 intel_clock_gating_init(i915); 120 intel_cx0_pll_power_save_wa(display); 121 intel_hpd_init(i915); 122 123 ret = __intel_display_driver_resume(display, state, ctx); 124 if (ret) 125 drm_err(&i915->drm, 126 "Restoring old state failed with %i\n", ret); 127 128 intel_hpd_poll_disable(i915); 129 } 130 131 drm_atomic_state_put(state); 132 unlock: 133 drm_modeset_drop_locks(ctx); 134 drm_modeset_acquire_fini(ctx); 135 mutex_unlock(&i915->drm.mode_config.mutex); 136 137 clear_bit_unlock(I915_RESET_MODESET, &to_gt(i915)->reset.flags); 138 } 139