brintos

brintos / linux-shallow public Read only

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