All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2.
@ 2016-05-02  8:57 Maarten Lankhorst
  2016-05-02  8:57 ` [PATCH 2/2] drm/i915: Add a way to test the modeset done during gpu reset, v3 Maarten Lankhorst
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-02  8:57 UTC (permalink / raw)
  To: intel-gfx; +Cc: drm-intel-fixes

This function would call drm_modeset_lock_all, while the suspend/resume
functions already have their own locking. Fix this by factoring out
__intel_display_resume, and calling the atomic helpers for duplicating
atomic state and disabling all crtc's during suspend.

Changes since v1:
- Deal with -EDEADLK right after lock_all and clean up calls
  to hw readout.
- Always take all modeset locks so updates during gpu reset are blocked.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
Cc: drm-intel-fixes@lists.freedesktop.org
---
 drivers/gpu/drm/i915/intel_display.c | 141 ++++++++++++++++++++++-------------
 1 file changed, 89 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2f36414702fe..4fb904f2bcf9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3144,27 +3144,83 @@ static void intel_update_primary_planes(struct drm_device *dev)
 	}
 }
 
+static int
+__intel_display_resume(struct drm_device *dev,
+		       struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i;
+
+	intel_modeset_setup_hw_state(dev);
+	i915_redisable_vga(dev);
+
+	if (!state)
+		return 0;
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		/*
+		 * Force recalculation even if we restore
+		 * current state. With fast modeset this may not result
+		 * in a modeset when the state is compatible.
+		 */
+		crtc_state->mode_changed = true;
+	}
+
+	return drm_atomic_commit(state);
+}
+
 void intel_prepare_reset(struct drm_device *dev)
 {
+	struct drm_atomic_state *state;
+	struct drm_modeset_acquire_ctx *pctx;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	int ret;
+
 	/* no reset support for gen2 */
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		return;
 
-	/* reset doesn't touch the display */
-	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+	drm_modeset_lock_all(dev);
+
+	/* reset doesn't touch the display, but flips might get nuked anyway, */
+	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
 		return;
 
-	drm_modeset_lock_all(dev);
+	pctx = dev->mode_config.acquire_ctx;
+
 	/*
 	 * Disabling the crtcs gracefully seems nicer. Also the
 	 * g33 docs say we should at least disable all the planes.
 	 */
-	intel_display_suspend(dev);
+
+	state = drm_atomic_helper_duplicate_state(dev, pctx);
+	if (IS_ERR(state)) {
+		ret = PTR_ERR(state);
+		state = NULL;
+		DRM_ERROR("Duplicating state failed with %i\n", ret);
+		goto err;
+	}
+
+	ret = drm_atomic_helper_disable_all(dev, pctx);
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		goto err;
+	}
+
+	dev_priv->modeset_restore_state = state;
+	state->acquire_ctx = pctx;
+	return;
+
+err:
+	drm_atomic_state_free(state);
 }
 
 void intel_finish_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
+	int ret;
 
 	/*
 	 * Flips in the rings will be nuked by the reset,
@@ -3177,6 +3233,8 @@ void intel_finish_reset(struct drm_device *dev)
 	if (IS_GEN2(dev))
 		return;
 
+	dev_priv->modeset_restore_state = NULL;
+
 	/* reset doesn't touch the display */
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
 		/*
@@ -3189,26 +3247,27 @@ void intel_finish_reset(struct drm_device *dev)
 		 * CS-based flips (which might get lost in gpu resets) any more.
 		 */
 		intel_update_primary_planes(dev);
-		return;
-	}
-
-	/*
-	 * The display has been reset as well,
-	 * so need a full re-initialization.
-	 */
-	intel_runtime_pm_disable_interrupts(dev_priv);
-	intel_runtime_pm_enable_interrupts(dev_priv);
+	} else {
+		/*
+		 * The display has been reset as well,
+		 * so need a full re-initialization.
+		 */
+		intel_runtime_pm_disable_interrupts(dev_priv);
+		intel_runtime_pm_enable_interrupts(dev_priv);
 
-	intel_modeset_init_hw(dev);
+		intel_modeset_init_hw(dev);
 
-	spin_lock_irq(&dev_priv->irq_lock);
-	if (dev_priv->display.hpd_irq_setup)
-		dev_priv->display.hpd_irq_setup(dev);
-	spin_unlock_irq(&dev_priv->irq_lock);
+		spin_lock_irq(&dev_priv->irq_lock);
+		if (dev_priv->display.hpd_irq_setup)
+			dev_priv->display.hpd_irq_setup(dev);
+		spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_display_resume(dev);
+		ret = __intel_display_resume(dev, state);
+		if (ret)
+			DRM_ERROR("Restoring old state failed with %i\n", ret);
 
-	intel_hpd_init(dev_priv);
+		intel_hpd_init(dev_priv);
+	}
 
 	drm_modeset_unlock_all(dev);
 }
@@ -15957,9 +16016,10 @@ void intel_display_resume(struct drm_device *dev)
 	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
 	struct drm_modeset_acquire_ctx ctx;
 	int ret;
-	bool setup = false;
 
 	dev_priv->modeset_restore_state = NULL;
+	if (state)
+		state->acquire_ctx = &ctx;
 
 	/*
 	 * This is a cludge because with real atomic modeset mode_config.mutex
@@ -15970,40 +16030,17 @@ void intel_display_resume(struct drm_device *dev)
 	mutex_lock(&dev->mode_config.mutex);
 	drm_modeset_acquire_init(&ctx, 0);
 
-retry:
-	ret = drm_modeset_lock_all_ctx(dev, &ctx);
-
-	if (ret == 0 && !setup) {
-		setup = true;
-
-		intel_modeset_setup_hw_state(dev);
-		i915_redisable_vga(dev);
-	}
-
-	if (ret == 0 && state) {
-		struct drm_crtc_state *crtc_state;
-		struct drm_crtc *crtc;
-		int i;
-
-		state->acquire_ctx = &ctx;
-
-		for_each_crtc_in_state(state, crtc, crtc_state, i) {
-			/*
-			 * Force recalculation even if we restore
-			 * current state. With fast modeset this may not result
-			 * in a modeset when the state is compatible.
-			 */
-			crtc_state->mode_changed = true;
-		}
-
-		ret = drm_atomic_commit(state);
-	}
+	while (1) {
+		ret = drm_modeset_lock_all_ctx(dev, &ctx);
+		if (ret != -EDEADLK)
+			break;
 
-	if (ret == -EDEADLK) {
 		drm_modeset_backoff(&ctx);
-		goto retry;
 	}
 
+	ret = __intel_display_resume(dev, state);
+	WARN_ON(ret == -EDEADLK);
+
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 	mutex_unlock(&dev->mode_config.mutex);
-- 
2.5.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] drm/i915: Add a way to test the modeset done during gpu reset, v3.
  2016-05-02  8:57 [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2 Maarten Lankhorst
@ 2016-05-02  8:57 ` Maarten Lankhorst
  2016-05-02  9:59 ` ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/i915: Fix modeset handling during gpu reset, v2 Patchwork
  2016-05-06 13:06 ` [PATCH 1/2] " Ville Syrjälä
  2 siblings, 0 replies; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-02  8:57 UTC (permalink / raw)
  To: intel-gfx

Add force_reset_modeset_test as a parameter to force the modeset path during gpu reset.
This allows a IGT test to set the knob and trigger a hang to force the gpu reset,
even on platforms that wouldn't otherwise require it.

Changes since v1:
- Split out fix to separate commit.
Changes since v2:
- This commit is purely about force_reset_modeset_test now.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Testcase: drv_hangman.reset-with-forced-modeset
---
 drivers/gpu/drm/i915/i915_params.c   |  6 ++++++
 drivers/gpu/drm/i915/i915_params.h   |  1 +
 drivers/gpu/drm/i915/intel_display.c | 30 +++++++++++++++++++-----------
 3 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 383c076919ed..ec3a03bfe3b0 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -45,6 +45,7 @@ struct i915_params i915 __read_mostly = {
 	.fastboot = 0,
 	.prefault_disable = 0,
 	.load_detect_test = 0,
+	.force_reset_modeset_test = 0,
 	.reset = true,
 	.invert_brightness = 0,
 	.disable_display = 0,
@@ -159,6 +160,11 @@ MODULE_PARM_DESC(load_detect_test,
 	"Force-enable the VGA load detect code for testing (default:false). "
 	"For developers only.");
 
+module_param_named_unsafe(force_reset_modeset_test, i915.force_reset_modeset_test, bool, 0600);
+MODULE_PARM_DESC(force_reset_modeset_test,
+	"Force a modeset during gpu reset for testing (default:false). "
+	"For developers only.");
+
 module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600);
 MODULE_PARM_DESC(invert_brightness,
 	"Invert backlight brightness "
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 65e73dd7d970..76c556a30461 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -55,6 +55,7 @@ struct i915_params {
 	bool fastboot;
 	bool prefault_disable;
 	bool load_detect_test;
+	bool force_reset_modeset_test;
 	bool reset;
 	bool disable_display;
 	bool enable_guc_submission;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4fb904f2bcf9..153039cc3ae8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3184,7 +3184,8 @@ void intel_prepare_reset(struct drm_device *dev)
 	drm_modeset_lock_all(dev);
 
 	/* reset doesn't touch the display, but flips might get nuked anyway, */
-	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
+	if (!i915.force_reset_modeset_test &&
+	    (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv)))
 		return;
 
 	pctx = dev->mode_config.acquire_ctx;
@@ -3237,16 +3238,23 @@ void intel_finish_reset(struct drm_device *dev)
 
 	/* reset doesn't touch the display */
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
-		/*
-		 * Flips in the rings have been nuked by the reset,
-		 * so update the base address of all primary
-		 * planes to the the last fb to make sure we're
-		 * showing the correct fb after a reset.
-		 *
-		 * FIXME: Atomic will make this obsolete since we won't schedule
-		 * CS-based flips (which might get lost in gpu resets) any more.
-		 */
-		intel_update_primary_planes(dev);
+		if (!state) {
+			/*
+			 * Flips in the rings have been nuked by the reset,
+			 * so update the base address of all primary
+			 * planes to the the last fb to make sure we're
+			 * showing the correct fb after a reset.
+			 *
+			 * FIXME: Atomic will make this obsolete since we won't schedule
+			 * CS-based flips (which might get lost in gpu resets) any more.
+			 */
+			intel_update_primary_planes(dev);
+		} else {
+			ret = __intel_display_resume(dev, state);
+
+			if (ret)
+				DRM_ERROR("Restoring old state failed with %i\n", ret);
+		}
 	} else {
 		/*
 		 * The display has been reset as well,
-- 
2.5.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/i915: Fix modeset handling during gpu reset, v2.
  2016-05-02  8:57 [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2 Maarten Lankhorst
  2016-05-02  8:57 ` [PATCH 2/2] drm/i915: Add a way to test the modeset done during gpu reset, v3 Maarten Lankhorst
@ 2016-05-02  9:59 ` Patchwork
  2016-05-06 13:06 ` [PATCH 1/2] " Ville Syrjälä
  2 siblings, 0 replies; 10+ messages in thread
From: Patchwork @ 2016-05-02  9:59 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/2] drm/i915: Fix modeset handling during gpu reset, v2.
URL   : https://patchwork.freedesktop.org/series/6600/
State : failure

== Summary ==

Series 6600v1 Series without cover letter
http://patchwork.freedesktop.org/api/1.0/series/6600/revisions/1/mbox/

Test drv_hangman:
        Subgroup error-state-basic:
                pass       -> INCOMPLETE (snb-x220t)
                pass       -> INCOMPLETE (bdw-nuci7-2)
                pass       -> INCOMPLETE (ilk-hp8440p)
Test gem_ringfill:
        Subgroup basic-default-hang:
                pass       -> INCOMPLETE (snb-dellxps)
                pass       -> INCOMPLETE (skl-nuci5)
Test kms_pipe_crc_basic:
        Subgroup hang-read-crc-pipe-a:
                pass       -> INCOMPLETE (bdw-ultra)
                pass       -> INCOMPLETE (skl-i7k-2)
                pass       -> INCOMPLETE (byt-nuc)
        Subgroup hang-read-crc-pipe-b:
                skip       -> INCOMPLETE (bsw-nuc-2)
                pass       -> INCOMPLETE (hsw-gt2)
                pass       -> INCOMPLETE (ivb-t430s)

bdw-nuci7-2      total:5    pass:4    dwarn:0   dfail:0   fail:0   skip:0  
bdw-ultra        total:95   pass:83   dwarn:0   dfail:0   fail:0   skip:11 
bsw-nuc-2        total:87   pass:67   dwarn:0   dfail:0   fail:0   skip:19 
byt-nuc          total:53   pass:42   dwarn:0   dfail:0   fail:1   skip:9  
hsw-brixbox      total:21   pass:16   dwarn:0   dfail:0   fail:0   skip:4  
hsw-gt2          total:12   pass:11   dwarn:0   dfail:0   fail:0   skip:0  
ilk-hp8440p      total:43   pass:33   dwarn:0   dfail:0   fail:0   skip:9  
ivb-t430s        total:35   pass:31   dwarn:0   dfail:0   fail:0   skip:3  
skl-i7k-2        total:35   pass:30   dwarn:0   dfail:0   fail:0   skip:4  
skl-nuci5        total:48   pass:45   dwarn:0   dfail:0   fail:0   skip:2  
snb-dellxps      total:6    pass:4    dwarn:0   dfail:0   fail:0   skip:1  
snb-x220t        total:69   pass:55   dwarn:0   dfail:0   fail:0   skip:13 

Results at /archive/results/CI_IGT_test/Patchwork_2123/

5256d5ce241debab2267faf6dc2d5ad9eaca9554 drm-intel-nightly: 2016y-05m-02d-07h-51m-16s UTC integration manifest
7410f53 drm/i915: Add a way to test the modeset done during gpu reset, v3.
089f414 drm/i915: Fix modeset handling during gpu reset, v2.

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2.
  2016-05-02  8:57 [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2 Maarten Lankhorst
  2016-05-02  8:57 ` [PATCH 2/2] drm/i915: Add a way to test the modeset done during gpu reset, v3 Maarten Lankhorst
  2016-05-02  9:59 ` ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/i915: Fix modeset handling during gpu reset, v2 Patchwork
@ 2016-05-06 13:06 ` Ville Syrjälä
  2016-05-09 10:29   ` Maarten Lankhorst
  2016-05-09 11:04   ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3 Maarten Lankhorst
  2 siblings, 2 replies; 10+ messages in thread
From: Ville Syrjälä @ 2016-05-06 13:06 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx, drm-intel-fixes

On Mon, May 02, 2016 at 10:57:01AM +0200, Maarten Lankhorst wrote:
> This function would call drm_modeset_lock_all, while the suspend/resume
> functions already have their own locking. Fix this by factoring out
> __intel_display_resume, and calling the atomic helpers for duplicating
> atomic state and disabling all crtc's during suspend.
> 
> Changes since v1:
> - Deal with -EDEADLK right after lock_all and clean up calls
>   to hw readout.
> - Always take all modeset locks so updates during gpu reset are blocked.

Found this patch by accident. --in-reply-to would have helped a bit.

> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
> Cc: drm-intel-fixes@lists.freedesktop.org
> ---
>  drivers/gpu/drm/i915/intel_display.c | 141 ++++++++++++++++++++++-------------
>  1 file changed, 89 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2f36414702fe..4fb904f2bcf9 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3144,27 +3144,83 @@ static void intel_update_primary_planes(struct drm_device *dev)
>  	}
>  }
>  
> +static int
> +__intel_display_resume(struct drm_device *dev,
> +		       struct drm_atomic_state *state)
> +{
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_crtc *crtc;
> +	int i;
> +
> +	intel_modeset_setup_hw_state(dev);
> +	i915_redisable_vga(dev);
> +
> +	if (!state)
> +		return 0;
> +
> +	for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +		/*
> +		 * Force recalculation even if we restore
> +		 * current state. With fast modeset this may not result
> +		 * in a modeset when the state is compatible.
> +		 */
> +		crtc_state->mode_changed = true;
> +	}
> +
> +	return drm_atomic_commit(state);

The -EDEADLK warn could be here so we don't have to duplicate it in two
places perhaps? Extracting __intel_display_reset() could also be a separate
patch to make this stuff a bit easier to review.

Oh and BTW resume is also broken on platforms that have the force pipe A
quirk. I do have some patches lined up to nuke that quirk for good, which
I should probably post sooner rather than later. But those have at least
a theoretical chance of regressing something, so in the meantime I think
we'll still need to fix this thing for the normal resume path as well.

> +}
> +
>  void intel_prepare_reset(struct drm_device *dev)
>  {
> +	struct drm_atomic_state *state;
> +	struct drm_modeset_acquire_ctx *pctx;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	int ret;
> +
>  	/* no reset support for gen2 */
> -	if (IS_GEN2(dev))
> +	if (IS_GEN2(dev_priv))
>  		return;
>  
> -	/* reset doesn't touch the display */
> -	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
> +	drm_modeset_lock_all(dev);

Isn't that going to clash with the locking in
intel_update_primary_planes() ?

> +
> +	/* reset doesn't touch the display, but flips might get nuked anyway, */
> +	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
>  		return;
>  
> -	drm_modeset_lock_all(dev);
> +	pctx = dev->mode_config.acquire_ctx;

Still looks like power context.

> +
>  	/*
>  	 * Disabling the crtcs gracefully seems nicer. Also the
>  	 * g33 docs say we should at least disable all the planes.
>  	 */
> -	intel_display_suspend(dev);
> +
> +	state = drm_atomic_helper_duplicate_state(dev, pctx);
> +	if (IS_ERR(state)) {
> +		ret = PTR_ERR(state);
> +		state = NULL;
> +		DRM_ERROR("Duplicating state failed with %i\n", ret);
> +		goto err;
> +	}
> +
> +	ret = drm_atomic_helper_disable_all(dev, pctx);
> +	if (ret) {
> +		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
> +		goto err;
> +	}
> +
> +	dev_priv->modeset_restore_state = state;
> +	state->acquire_ctx = pctx;
> +	return;
> +
> +err:
> +	drm_atomic_state_free(state);
>  }
>  
>  void intel_finish_reset(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
> +	int ret;
>  
>  	/*
>  	 * Flips in the rings will be nuked by the reset,
> @@ -3177,6 +3233,8 @@ void intel_finish_reset(struct drm_device *dev)
>  	if (IS_GEN2(dev))
>  		return;
>  
> +	dev_priv->modeset_restore_state = NULL;
> +
>  	/* reset doesn't touch the display */
>  	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
>  		/*
> @@ -3189,26 +3247,27 @@ void intel_finish_reset(struct drm_device *dev)
>  		 * CS-based flips (which might get lost in gpu resets) any more.
>  		 */
>  		intel_update_primary_planes(dev);
> -		return;
> -	}
> -
> -	/*
> -	 * The display has been reset as well,
> -	 * so need a full re-initialization.
> -	 */
> -	intel_runtime_pm_disable_interrupts(dev_priv);
> -	intel_runtime_pm_enable_interrupts(dev_priv);
> +	} else {
> +		/*
> +		 * The display has been reset as well,
> +		 * so need a full re-initialization.
> +		 */
> +		intel_runtime_pm_disable_interrupts(dev_priv);
> +		intel_runtime_pm_enable_interrupts(dev_priv);
>  
> -	intel_modeset_init_hw(dev);
> +		intel_modeset_init_hw(dev);
>  
> -	spin_lock_irq(&dev_priv->irq_lock);
> -	if (dev_priv->display.hpd_irq_setup)
> -		dev_priv->display.hpd_irq_setup(dev);
> -	spin_unlock_irq(&dev_priv->irq_lock);
> +		spin_lock_irq(&dev_priv->irq_lock);
> +		if (dev_priv->display.hpd_irq_setup)
> +			dev_priv->display.hpd_irq_setup(dev);
> +		spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	intel_display_resume(dev);
> +		ret = __intel_display_resume(dev, state);
> +		if (ret)
> +			DRM_ERROR("Restoring old state failed with %i\n", ret);
>  
> -	intel_hpd_init(dev_priv);
> +		intel_hpd_init(dev_priv);
> +	}
>  
>  	drm_modeset_unlock_all(dev);
>  }
> @@ -15957,9 +16016,10 @@ void intel_display_resume(struct drm_device *dev)
>  	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
>  	struct drm_modeset_acquire_ctx ctx;
>  	int ret;
> -	bool setup = false;
>  
>  	dev_priv->modeset_restore_state = NULL;
> +	if (state)
> +		state->acquire_ctx = &ctx;
>  
>  	/*
>  	 * This is a cludge because with real atomic modeset mode_config.mutex
> @@ -15970,40 +16030,17 @@ void intel_display_resume(struct drm_device *dev)
>  	mutex_lock(&dev->mode_config.mutex);
>  	drm_modeset_acquire_init(&ctx, 0);
>  
> -retry:
> -	ret = drm_modeset_lock_all_ctx(dev, &ctx);
> -
> -	if (ret == 0 && !setup) {
> -		setup = true;
> -
> -		intel_modeset_setup_hw_state(dev);
> -		i915_redisable_vga(dev);
> -	}
> -
> -	if (ret == 0 && state) {
> -		struct drm_crtc_state *crtc_state;
> -		struct drm_crtc *crtc;
> -		int i;
> -
> -		state->acquire_ctx = &ctx;
> -
> -		for_each_crtc_in_state(state, crtc, crtc_state, i) {
> -			/*
> -			 * Force recalculation even if we restore
> -			 * current state. With fast modeset this may not result
> -			 * in a modeset when the state is compatible.
> -			 */
> -			crtc_state->mode_changed = true;
> -		}
> -
> -		ret = drm_atomic_commit(state);
> -	}
> +	while (1) {
> +		ret = drm_modeset_lock_all_ctx(dev, &ctx);
> +		if (ret != -EDEADLK)
> +			break;
>  
> -	if (ret == -EDEADLK) {
>  		drm_modeset_backoff(&ctx);
> -		goto retry;
>  	}
>  
> +	ret = __intel_display_resume(dev, state);

Shouldn't we skip this call if the lock_all failed?

> +	WARN_ON(ret == -EDEADLK);
> +
>  	drm_modeset_drop_locks(&ctx);
>  	drm_modeset_acquire_fini(&ctx);
>  	mutex_unlock(&dev->mode_config.mutex);
> -- 
> 2.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2.
  2016-05-06 13:06 ` [PATCH 1/2] " Ville Syrjälä
@ 2016-05-09 10:29   ` Maarten Lankhorst
  2016-05-09 11:04   ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3 Maarten Lankhorst
  1 sibling, 0 replies; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-09 10:29 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, drm-intel-fixes

Op 06-05-16 om 15:06 schreef Ville Syrjälä:
> On Mon, May 02, 2016 at 10:57:01AM +0200, Maarten Lankhorst wrote:
>> This function would call drm_modeset_lock_all, while the suspend/resume
>> functions already have their own locking. Fix this by factoring out
>> __intel_display_resume, and calling the atomic helpers for duplicating
>> atomic state and disabling all crtc's during suspend.
>>
>> Changes since v1:
>> - Deal with -EDEADLK right after lock_all and clean up calls
>>   to hw readout.
>> - Always take all modeset locks so updates during gpu reset are blocked.
> Found this patch by accident. --in-reply-to would have helped a bit.
>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
>> Cc: drm-intel-fixes@lists.freedesktop.org
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 141 ++++++++++++++++++++++-------------
>>  1 file changed, 89 insertions(+), 52 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 2f36414702fe..4fb904f2bcf9 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -3144,27 +3144,83 @@ static void intel_update_primary_planes(struct drm_device *dev)
>>  	}
>>  }
>>  
>> +static int
>> +__intel_display_resume(struct drm_device *dev,
>> +		       struct drm_atomic_state *state)
>> +{
>> +	struct drm_crtc_state *crtc_state;
>> +	struct drm_crtc *crtc;
>> +	int i;
>> +
>> +	intel_modeset_setup_hw_state(dev);
>> +	i915_redisable_vga(dev);
>> +
>> +	if (!state)
>> +		return 0;
>> +
>> +	for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> +		/*
>> +		 * Force recalculation even if we restore
>> +		 * current state. With fast modeset this may not result
>> +		 * in a modeset when the state is compatible.
>> +		 */
>> +		crtc_state->mode_changed = true;
>> +	}
>> +
>> +	return drm_atomic_commit(state);
> The -EDEADLK warn could be here so we don't have to duplicate it in two
> places perhaps? Extracting __intel_display_reset() could also be a separate
> patch to make this stuff a bit easier to review.
>
> Oh and BTW resume is also broken on platforms that have the force pipe A
> quirk. I do have some patches lined up to nuke that quirk for good, which
> I should probably post sooner rather than later. But those have at least
> a theoretical chance of regressing something, so in the meantime I think
> we'll still need to fix this thing for the normal resume path as well.
>
>> +}
>> +
>>  void intel_prepare_reset(struct drm_device *dev)
>>  {
>> +	struct drm_atomic_state *state;
>> +	struct drm_modeset_acquire_ctx *pctx;
>> +	struct drm_i915_private *dev_priv = to_i915(dev);
>> +	int ret;
>> +
>>  	/* no reset support for gen2 */
>> -	if (IS_GEN2(dev))
>> +	if (IS_GEN2(dev_priv))
>>  		return;
>>  
>> -	/* reset doesn't touch the display */
>> -	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
>> +	drm_modeset_lock_all(dev);
> Isn't that going to clash with the locking in
> intel_update_primary_planes() ?
Oops indeed, thanks for catching.
>> +
>> +	/* reset doesn't touch the display, but flips might get nuked anyway, */
>> +	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
>>  		return;
>>  
>> -	drm_modeset_lock_all(dev);
>> +	pctx = dev->mode_config.acquire_ctx;
> Still looks like power context.
Will change to ctx.
>> +
>>  	/*
>>  	 * Disabling the crtcs gracefully seems nicer. Also the
>>  	 * g33 docs say we should at least disable all the planes.
>>  	 */
>> -	intel_display_suspend(dev);
>> +
>> +	state = drm_atomic_helper_duplicate_state(dev, pctx);
>> +	if (IS_ERR(state)) {
>> +		ret = PTR_ERR(state);
>> +		state = NULL;
>> +		DRM_ERROR("Duplicating state failed with %i\n", ret);
>> +		goto err;
>> +	}
>> +
>> +	ret = drm_atomic_helper_disable_all(dev, pctx);
>> +	if (ret) {
>> +		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
>> +		goto err;
>> +	}
>> +
>> +	dev_priv->modeset_restore_state = state;
>> +	state->acquire_ctx = pctx;
>> +	return;
>> +
>> +err:
>> +	drm_atomic_state_free(state);
>>  }
>>  
>>  void intel_finish_reset(struct drm_device *dev)
>>  {
>>  	struct drm_i915_private *dev_priv = to_i915(dev);
>> +	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
>> +	int ret;
>>  
>>  	/*
>>  	 * Flips in the rings will be nuked by the reset,
>> @@ -3177,6 +3233,8 @@ void intel_finish_reset(struct drm_device *dev)
>>  	if (IS_GEN2(dev))
>>  		return;
>>  
>> +	dev_priv->modeset_restore_state = NULL;
>> +
>>  	/* reset doesn't touch the display */
>>  	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
>>  		/*
>> @@ -3189,26 +3247,27 @@ void intel_finish_reset(struct drm_device *dev)
>>  		 * CS-based flips (which might get lost in gpu resets) any more.
>>  		 */
>>  		intel_update_primary_planes(dev);
>> -		return;
>> -	}
>> -
>> -	/*
>> -	 * The display has been reset as well,
>> -	 * so need a full re-initialization.
>> -	 */
>> -	intel_runtime_pm_disable_interrupts(dev_priv);
>> -	intel_runtime_pm_enable_interrupts(dev_priv);
>> +	} else {
>> +		/*
>> +		 * The display has been reset as well,
>> +		 * so need a full re-initialization.
>> +		 */
>> +		intel_runtime_pm_disable_interrupts(dev_priv);
>> +		intel_runtime_pm_enable_interrupts(dev_priv);
>>  
>> -	intel_modeset_init_hw(dev);
>> +		intel_modeset_init_hw(dev);
>>  
>> -	spin_lock_irq(&dev_priv->irq_lock);
>> -	if (dev_priv->display.hpd_irq_setup)
>> -		dev_priv->display.hpd_irq_setup(dev);
>> -	spin_unlock_irq(&dev_priv->irq_lock);
>> +		spin_lock_irq(&dev_priv->irq_lock);
>> +		if (dev_priv->display.hpd_irq_setup)
>> +			dev_priv->display.hpd_irq_setup(dev);
>> +		spin_unlock_irq(&dev_priv->irq_lock);
>>  
>> -	intel_display_resume(dev);
>> +		ret = __intel_display_resume(dev, state);
>> +		if (ret)
>> +			DRM_ERROR("Restoring old state failed with %i\n", ret);
>>  
>> -	intel_hpd_init(dev_priv);
>> +		intel_hpd_init(dev_priv);
>> +	}
>>  
>>  	drm_modeset_unlock_all(dev);
>>  }
>> @@ -15957,9 +16016,10 @@ void intel_display_resume(struct drm_device *dev)
>>  	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
>>  	struct drm_modeset_acquire_ctx ctx;
>>  	int ret;
>> -	bool setup = false;
>>  
>>  	dev_priv->modeset_restore_state = NULL;
>> +	if (state)
>> +		state->acquire_ctx = &ctx;
>>  
>>  	/*
>>  	 * This is a cludge because with real atomic modeset mode_config.mutex
>> @@ -15970,40 +16030,17 @@ void intel_display_resume(struct drm_device *dev)
>>  	mutex_lock(&dev->mode_config.mutex);
>>  	drm_modeset_acquire_init(&ctx, 0);
>>  
>> -retry:
>> -	ret = drm_modeset_lock_all_ctx(dev, &ctx);
>> -
>> -	if (ret == 0 && !setup) {
>> -		setup = true;
>> -
>> -		intel_modeset_setup_hw_state(dev);
>> -		i915_redisable_vga(dev);
>> -	}
>> -
>> -	if (ret == 0 && state) {
>> -		struct drm_crtc_state *crtc_state;
>> -		struct drm_crtc *crtc;
>> -		int i;
>> -
>> -		state->acquire_ctx = &ctx;
>> -
>> -		for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> -			/*
>> -			 * Force recalculation even if we restore
>> -			 * current state. With fast modeset this may not result
>> -			 * in a modeset when the state is compatible.
>> -			 */
>> -			crtc_state->mode_changed = true;
>> -		}
>> -
>> -		ret = drm_atomic_commit(state);
>> -	}
>> +	while (1) {
>> +		ret = drm_modeset_lock_all_ctx(dev, &ctx);
>> +		if (ret != -EDEADLK)
>> +			break;
>>  
>> -	if (ret == -EDEADLK) {
>>  		drm_modeset_backoff(&ctx);
>> -		goto retry;
>>  	}
>>  
>> +	ret = __intel_display_resume(dev, state);
> Shouldn't we skip this call if the lock_all failed?
I guess for paranoia I could, but the locking can only fail with EDEADLK or EALREADY. EALREADY is mapped to 0 since multiple locking calls are allowed,
so can realistically only fail with -EDEADLK, won't even be able to fail with -EINTR in the future since s/r is not interruptible.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3.
  2016-05-06 13:06 ` [PATCH 1/2] " Ville Syrjälä
  2016-05-09 10:29   ` Maarten Lankhorst
@ 2016-05-09 11:04   ` Maarten Lankhorst
  2016-05-09 12:54     ` Ville Syrjälä
  1 sibling, 1 reply; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-09 11:04 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, drm-intel-fixes

This function would call drm_modeset_lock_all, while the suspend/resume
functions already have their own locking. Fix this by factoring out
__intel_display_resume, and calling the atomic helpers for duplicating
atomic state and disabling all crtc's during suspend.

Changes since v1:
- Deal with -EDEADLK right after lock_all and clean up calls
  to hw readout.
- Always take all modeset locks so updates during gpu reset are blocked.
Changes since v2:
- Fix deadlock in intel_update_primary_planes.
- Move WARN_ON(EDEADLK) to __intel_display_resume.
- pctx -> ctx
- only call __intel_display_resume on success in intel_display_resume.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
Cc: drm-intel-fixes@lists.freedesktop.org
---
 drivers/gpu/drm/i915/intel_display.c | 150 ++++++++++++++++++++++-------------
 1 file changed, 93 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 14e05091c397..6faa529f35df 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3130,41 +3130,96 @@ static void intel_update_primary_planes(struct drm_device *dev)
 
 	for_each_crtc(dev, crtc) {
 		struct intel_plane *plane = to_intel_plane(crtc->primary);
-		struct intel_plane_state *plane_state;
-
-		drm_modeset_lock_crtc(crtc, &plane->base);
-		plane_state = to_intel_plane_state(plane->base.state);
+		struct intel_plane_state *plane_state =
+			to_intel_plane_state(plane->base.state);
 
 		if (plane_state->visible)
 			plane->update_plane(&plane->base,
 					    to_intel_crtc_state(crtc->state),
 					    plane_state);
+	}
+}
+
+static int
+__intel_display_resume(struct drm_device *dev,
+		       struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	intel_modeset_setup_hw_state(dev);
+	i915_redisable_vga(dev);
 
-		drm_modeset_unlock_crtc(crtc);
+	if (!state)
+		return 0;
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		/*
+		 * Force recalculation even if we restore
+		 * current state. With fast modeset this may not result
+		 * in a modeset when the state is compatible.
+		 */
+		crtc_state->mode_changed = true;
 	}
+
+	ret = drm_atomic_commit(state);
+
+	WARN_ON(ret == -EDEADLK);
+	return ret;
 }
 
 void intel_prepare_reset(struct drm_device *dev)
 {
+	struct drm_atomic_state *state;
+	struct drm_modeset_acquire_ctx *ctx;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	int ret;
+
 	/* no reset support for gen2 */
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		return;
 
-	/* reset doesn't touch the display */
-	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+	drm_modeset_lock_all(dev);
+
+	/* reset doesn't touch the display, but flips might get nuked anyway, */
+	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
 		return;
 
-	drm_modeset_lock_all(dev);
+	ctx = dev->mode_config.acquire_ctx;
+
 	/*
 	 * Disabling the crtcs gracefully seems nicer. Also the
 	 * g33 docs say we should at least disable all the planes.
 	 */
-	intel_display_suspend(dev);
+
+	state = drm_atomic_helper_duplicate_state(dev, ctx);
+	if (IS_ERR(state)) {
+		ret = PTR_ERR(state);
+		state = NULL;
+		DRM_ERROR("Duplicating state failed with %i\n", ret);
+		goto err;
+	}
+
+	ret = drm_atomic_helper_disable_all(dev, ctx);
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		goto err;
+	}
+
+	dev_priv->modeset_restore_state = state;
+	state->acquire_ctx = ctx;
+	return;
+
+err:
+	drm_atomic_state_free(state);
 }
 
 void intel_finish_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
+	int ret;
 
 	/*
 	 * Flips in the rings will be nuked by the reset,
@@ -3177,6 +3232,8 @@ void intel_finish_reset(struct drm_device *dev)
 	if (IS_GEN2(dev))
 		return;
 
+	dev_priv->modeset_restore_state = NULL;
+
 	/* reset doesn't touch the display */
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
 		/*
@@ -3189,26 +3246,27 @@ void intel_finish_reset(struct drm_device *dev)
 		 * CS-based flips (which might get lost in gpu resets) any more.
 		 */
 		intel_update_primary_planes(dev);
-		return;
-	}
-
-	/*
-	 * The display has been reset as well,
-	 * so need a full re-initialization.
-	 */
-	intel_runtime_pm_disable_interrupts(dev_priv);
-	intel_runtime_pm_enable_interrupts(dev_priv);
+	} else {
+		/*
+		 * The display has been reset as well,
+		 * so need a full re-initialization.
+		 */
+		intel_runtime_pm_disable_interrupts(dev_priv);
+		intel_runtime_pm_enable_interrupts(dev_priv);
 
-	intel_modeset_init_hw(dev);
+		intel_modeset_init_hw(dev);
 
-	spin_lock_irq(&dev_priv->irq_lock);
-	if (dev_priv->display.hpd_irq_setup)
-		dev_priv->display.hpd_irq_setup(dev);
-	spin_unlock_irq(&dev_priv->irq_lock);
+		spin_lock_irq(&dev_priv->irq_lock);
+		if (dev_priv->display.hpd_irq_setup)
+			dev_priv->display.hpd_irq_setup(dev);
+		spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_display_resume(dev);
+		ret = __intel_display_resume(dev, state);
+		if (ret)
+			DRM_ERROR("Restoring old state failed with %i\n", ret);
 
-	intel_hpd_init(dev_priv);
+		intel_hpd_init(dev_priv);
+	}
 
 	drm_modeset_unlock_all(dev);
 }
@@ -15955,9 +16013,10 @@ void intel_display_resume(struct drm_device *dev)
 	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
 	struct drm_modeset_acquire_ctx ctx;
 	int ret;
-	bool setup = false;
 
 	dev_priv->modeset_restore_state = NULL;
+	if (state)
+		state->acquire_ctx = &ctx;
 
 	/*
 	 * This is a cludge because with real atomic modeset mode_config.mutex
@@ -15968,40 +16027,17 @@ void intel_display_resume(struct drm_device *dev)
 	mutex_lock(&dev->mode_config.mutex);
 	drm_modeset_acquire_init(&ctx, 0);
 
-retry:
-	ret = drm_modeset_lock_all_ctx(dev, &ctx);
-
-	if (ret == 0 && !setup) {
-		setup = true;
-
-		intel_modeset_setup_hw_state(dev);
-		i915_redisable_vga(dev);
-	}
-
-	if (ret == 0 && state) {
-		struct drm_crtc_state *crtc_state;
-		struct drm_crtc *crtc;
-		int i;
-
-		state->acquire_ctx = &ctx;
-
-		for_each_crtc_in_state(state, crtc, crtc_state, i) {
-			/*
-			 * Force recalculation even if we restore
-			 * current state. With fast modeset this may not result
-			 * in a modeset when the state is compatible.
-			 */
-			crtc_state->mode_changed = true;
-		}
-
-		ret = drm_atomic_commit(state);
-	}
+	while (1) {
+		ret = drm_modeset_lock_all_ctx(dev, &ctx);
+		if (ret != -EDEADLK)
+			break;
 
-	if (ret == -EDEADLK) {
 		drm_modeset_backoff(&ctx);
-		goto retry;
 	}
 
+	if (!ret)
+		ret = __intel_display_resume(dev, state);
+
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 	mutex_unlock(&dev->mode_config.mutex);
-- 
2.5.5


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3.
  2016-05-09 11:04   ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3 Maarten Lankhorst
@ 2016-05-09 12:54     ` Ville Syrjälä
  2016-05-10  7:48       ` Daniel Vetter
  0 siblings, 1 reply; 10+ messages in thread
From: Ville Syrjälä @ 2016-05-09 12:54 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx, drm-intel-fixes

On Mon, May 09, 2016 at 01:04:21PM +0200, Maarten Lankhorst wrote:
> This function would call drm_modeset_lock_all, while the suspend/resume
> functions already have their own locking. Fix this by factoring out
> __intel_display_resume, and calling the atomic helpers for duplicating
> atomic state and disabling all crtc's during suspend.
> 
> Changes since v1:
> - Deal with -EDEADLK right after lock_all and clean up calls
>   to hw readout.
> - Always take all modeset locks so updates during gpu reset are blocked.
> Changes since v2:
> - Fix deadlock in intel_update_primary_planes.
> - Move WARN_ON(EDEADLK) to __intel_display_resume.
> - pctx -> ctx
> - only call __intel_display_resume on success in intel_display_resume.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
> Cc: drm-intel-fixes@lists.freedesktop.org
> ---
>  drivers/gpu/drm/i915/intel_display.c | 150 ++++++++++++++++++++++-------------
>  1 file changed, 93 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 14e05091c397..6faa529f35df 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3130,41 +3130,96 @@ static void intel_update_primary_planes(struct drm_device *dev)
>  
>  	for_each_crtc(dev, crtc) {
>  		struct intel_plane *plane = to_intel_plane(crtc->primary);
> -		struct intel_plane_state *plane_state;
> -
> -		drm_modeset_lock_crtc(crtc, &plane->base);
> -		plane_state = to_intel_plane_state(plane->base.state);
> +		struct intel_plane_state *plane_state =
> +			to_intel_plane_state(plane->base.state);
>  
>  		if (plane_state->visible)
>  			plane->update_plane(&plane->base,
>  					    to_intel_crtc_state(crtc->state),
>  					    plane_state);
> +	}
> +}
> +
> +static int
> +__intel_display_resume(struct drm_device *dev,
> +		       struct drm_atomic_state *state)
> +{
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_crtc *crtc;
> +	int i, ret;
> +
> +	intel_modeset_setup_hw_state(dev);
> +	i915_redisable_vga(dev);
>  
> -		drm_modeset_unlock_crtc(crtc);
> +	if (!state)
> +		return 0;

Thank you diff for making things illegible.

I'm still not convinced we should be changing the locking scheme
here, especially in what's supposed to be just a fix.

In general, I'm not sure we want ->detect() and other irrelevant
stuff to block the GPU reset. The nice thing about g4x+ reset so
far has been that it's almost unnoticeable. Of course if it's a
genuine GPU hang the screen will probably have been frozen for
quite a while when we initiate the reset, so perhaps that's not
a huge real world issue.

Anyways, I kinda just want this fixed now, so I'll just toss in my
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

BTW as a followup I think we would actually want gen2 to take the
g4x+ path. There won't have been a reset, but the flips in the
ring will still never complete so our idea of frontbuffer may be
out of sync with the hardware, and so we should fix it up.

> +
> +	for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +		/*
> +		 * Force recalculation even if we restore
> +		 * current state. With fast modeset this may not result
> +		 * in a modeset when the state is compatible.
> +		 */
> +		crtc_state->mode_changed = true;
>  	}
> +
> +	ret = drm_atomic_commit(state);
> +
> +	WARN_ON(ret == -EDEADLK);
> +	return ret;
>  }
>  
>  void intel_prepare_reset(struct drm_device *dev)
>  {
> +	struct drm_atomic_state *state;
> +	struct drm_modeset_acquire_ctx *ctx;
> +	struct drm_i915_private *dev_priv = to_i915(dev);
> +	int ret;
> +
>  	/* no reset support for gen2 */
> -	if (IS_GEN2(dev))
> +	if (IS_GEN2(dev_priv))
>  		return;
>  
> -	/* reset doesn't touch the display */
> -	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
> +	drm_modeset_lock_all(dev);


> +
> +	/* reset doesn't touch the display, but flips might get nuked anyway, */
> +	if (INTEL_INFO(dev_priv)->gen >= 5 || IS_G4X(dev_priv))
>  		return;
>  
> -	drm_modeset_lock_all(dev);
> +	ctx = dev->mode_config.acquire_ctx;
> +
>  	/*
>  	 * Disabling the crtcs gracefully seems nicer. Also the
>  	 * g33 docs say we should at least disable all the planes.
>  	 */
> -	intel_display_suspend(dev);
> +
> +	state = drm_atomic_helper_duplicate_state(dev, ctx);
> +	if (IS_ERR(state)) {
> +		ret = PTR_ERR(state);
> +		state = NULL;
> +		DRM_ERROR("Duplicating state failed with %i\n", ret);
> +		goto err;
> +	}
> +
> +	ret = drm_atomic_helper_disable_all(dev, ctx);
> +	if (ret) {
> +		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
> +		goto err;
> +	}
> +
> +	dev_priv->modeset_restore_state = state;
> +	state->acquire_ctx = ctx;
> +	return;
> +
> +err:
> +	drm_atomic_state_free(state);
>  }
>  
>  void intel_finish_reset(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
> +	int ret;
>  
>  	/*
>  	 * Flips in the rings will be nuked by the reset,
> @@ -3177,6 +3232,8 @@ void intel_finish_reset(struct drm_device *dev)
>  	if (IS_GEN2(dev))
>  		return;
>  
> +	dev_priv->modeset_restore_state = NULL;
> +
>  	/* reset doesn't touch the display */
>  	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) {
>  		/*
> @@ -3189,26 +3246,27 @@ void intel_finish_reset(struct drm_device *dev)
>  		 * CS-based flips (which might get lost in gpu resets) any more.
>  		 */
>  		intel_update_primary_planes(dev);
> -		return;
> -	}
> -
> -	/*
> -	 * The display has been reset as well,
> -	 * so need a full re-initialization.
> -	 */
> -	intel_runtime_pm_disable_interrupts(dev_priv);
> -	intel_runtime_pm_enable_interrupts(dev_priv);
> +	} else {
> +		/*
> +		 * The display has been reset as well,
> +		 * so need a full re-initialization.
> +		 */
> +		intel_runtime_pm_disable_interrupts(dev_priv);
> +		intel_runtime_pm_enable_interrupts(dev_priv);
>  
> -	intel_modeset_init_hw(dev);
> +		intel_modeset_init_hw(dev);
>  
> -	spin_lock_irq(&dev_priv->irq_lock);
> -	if (dev_priv->display.hpd_irq_setup)
> -		dev_priv->display.hpd_irq_setup(dev);
> -	spin_unlock_irq(&dev_priv->irq_lock);
> +		spin_lock_irq(&dev_priv->irq_lock);
> +		if (dev_priv->display.hpd_irq_setup)
> +			dev_priv->display.hpd_irq_setup(dev);
> +		spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	intel_display_resume(dev);
> +		ret = __intel_display_resume(dev, state);
> +		if (ret)
> +			DRM_ERROR("Restoring old state failed with %i\n", ret);
>  
> -	intel_hpd_init(dev_priv);
> +		intel_hpd_init(dev_priv);
> +	}
>  
>  	drm_modeset_unlock_all(dev);
>  }
> @@ -15955,9 +16013,10 @@ void intel_display_resume(struct drm_device *dev)
>  	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
>  	struct drm_modeset_acquire_ctx ctx;
>  	int ret;
> -	bool setup = false;
>  
>  	dev_priv->modeset_restore_state = NULL;
> +	if (state)
> +		state->acquire_ctx = &ctx;
>  
>  	/*
>  	 * This is a cludge because with real atomic modeset mode_config.mutex
> @@ -15968,40 +16027,17 @@ void intel_display_resume(struct drm_device *dev)
>  	mutex_lock(&dev->mode_config.mutex);
>  	drm_modeset_acquire_init(&ctx, 0);
>  
> -retry:
> -	ret = drm_modeset_lock_all_ctx(dev, &ctx);
> -
> -	if (ret == 0 && !setup) {
> -		setup = true;
> -
> -		intel_modeset_setup_hw_state(dev);
> -		i915_redisable_vga(dev);
> -	}
> -
> -	if (ret == 0 && state) {
> -		struct drm_crtc_state *crtc_state;
> -		struct drm_crtc *crtc;
> -		int i;
> -
> -		state->acquire_ctx = &ctx;
> -
> -		for_each_crtc_in_state(state, crtc, crtc_state, i) {
> -			/*
> -			 * Force recalculation even if we restore
> -			 * current state. With fast modeset this may not result
> -			 * in a modeset when the state is compatible.
> -			 */
> -			crtc_state->mode_changed = true;
> -		}
> -
> -		ret = drm_atomic_commit(state);
> -	}
> +	while (1) {
> +		ret = drm_modeset_lock_all_ctx(dev, &ctx);
> +		if (ret != -EDEADLK)
> +			break;
>  
> -	if (ret == -EDEADLK) {
>  		drm_modeset_backoff(&ctx);
> -		goto retry;
>  	}
>  
> +	if (!ret)
> +		ret = __intel_display_resume(dev, state);
> +
>  	drm_modeset_drop_locks(&ctx);
>  	drm_modeset_acquire_fini(&ctx);
>  	mutex_unlock(&dev->mode_config.mutex);
> -- 
> 2.5.5
> 

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3.
  2016-05-09 12:54     ` Ville Syrjälä
@ 2016-05-10  7:48       ` Daniel Vetter
  2016-05-10 17:08         ` Maarten Lankhorst
  2016-05-11  8:35         ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v4 Maarten Lankhorst
  0 siblings, 2 replies; 10+ messages in thread
From: Daniel Vetter @ 2016-05-10  7:48 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: drm-intel-fixes, intel-gfx

On Mon, May 09, 2016 at 03:54:15PM +0300, Ville Syrjälä wrote:
> On Mon, May 09, 2016 at 01:04:21PM +0200, Maarten Lankhorst wrote:
> > This function would call drm_modeset_lock_all, while the suspend/resume
> > functions already have their own locking. Fix this by factoring out
> > __intel_display_resume, and calling the atomic helpers for duplicating
> > atomic state and disabling all crtc's during suspend.
> > 
> > Changes since v1:
> > - Deal with -EDEADLK right after lock_all and clean up calls
> >   to hw readout.
> > - Always take all modeset locks so updates during gpu reset are blocked.
> > Changes since v2:
> > - Fix deadlock in intel_update_primary_planes.
> > - Move WARN_ON(EDEADLK) to __intel_display_resume.
> > - pctx -> ctx
> > - only call __intel_display_resume on success in intel_display_resume.
> > 
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
> > Cc: drm-intel-fixes@lists.freedesktop.org
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 150 ++++++++++++++++++++++-------------
> >  1 file changed, 93 insertions(+), 57 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 14e05091c397..6faa529f35df 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -3130,41 +3130,96 @@ static void intel_update_primary_planes(struct drm_device *dev)
> >  
> >  	for_each_crtc(dev, crtc) {
> >  		struct intel_plane *plane = to_intel_plane(crtc->primary);
> > -		struct intel_plane_state *plane_state;
> > -
> > -		drm_modeset_lock_crtc(crtc, &plane->base);
> > -		plane_state = to_intel_plane_state(plane->base.state);
> > +		struct intel_plane_state *plane_state =
> > +			to_intel_plane_state(plane->base.state);
> >  
> >  		if (plane_state->visible)
> >  			plane->update_plane(&plane->base,
> >  					    to_intel_crtc_state(crtc->state),
> >  					    plane_state);
> > +	}
> > +}
> > +
> > +static int
> > +__intel_display_resume(struct drm_device *dev,
> > +		       struct drm_atomic_state *state)
> > +{
> > +	struct drm_crtc_state *crtc_state;
> > +	struct drm_crtc *crtc;
> > +	int i, ret;
> > +
> > +	intel_modeset_setup_hw_state(dev);
> > +	i915_redisable_vga(dev);
> >  
> > -		drm_modeset_unlock_crtc(crtc);
> > +	if (!state)
> > +		return 0;
> 
> Thank you diff for making things illegible.
> 
> I'm still not convinced we should be changing the locking scheme
> here, especially in what's supposed to be just a fix.
> 
> In general, I'm not sure we want ->detect() and other irrelevant
> stuff to block the GPU reset. The nice thing about g4x+ reset so
> far has been that it's almost unnoticeable. Of course if it's a
> genuine GPU hang the screen will probably have been frozen for
> quite a while when we initiate the reset, so perhaps that's not
> a huge real world issue.

We don't really need dev->mode_config.mutex for atomic commits, so taking
that out and use drm_modeset_lock_all_ctx would give you that.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3.
  2016-05-10  7:48       ` Daniel Vetter
@ 2016-05-10 17:08         ` Maarten Lankhorst
  2016-05-11  8:35         ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v4 Maarten Lankhorst
  1 sibling, 0 replies; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-10 17:08 UTC (permalink / raw)
  To: Daniel Vetter, Ville Syrjälä; +Cc: intel-gfx, drm-intel-fixes

Op 10-05-16 om 09:48 schreef Daniel Vetter:
> On Mon, May 09, 2016 at 03:54:15PM +0300, Ville Syrjälä wrote:
>> On Mon, May 09, 2016 at 01:04:21PM +0200, Maarten Lankhorst wrote:
>>> This function would call drm_modeset_lock_all, while the suspend/resume
>>> functions already have their own locking. Fix this by factoring out
>>> __intel_display_resume, and calling the atomic helpers for duplicating
>>> atomic state and disabling all crtc's during suspend.
>>>
>>> Changes since v1:
>>> - Deal with -EDEADLK right after lock_all and clean up calls
>>>   to hw readout.
>>> - Always take all modeset locks so updates during gpu reset are blocked.
>>> Changes since v2:
>>> - Fix deadlock in intel_update_primary_planes.
>>> - Move WARN_ON(EDEADLK) to __intel_display_resume.
>>> - pctx -> ctx
>>> - only call __intel_display_resume on success in intel_display_resume.
>>>
>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
>>> Cc: drm-intel-fixes@lists.freedesktop.org
>>> ---
>>>  drivers/gpu/drm/i915/intel_display.c | 150 ++++++++++++++++++++++-------------
>>>  1 file changed, 93 insertions(+), 57 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 14e05091c397..6faa529f35df 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -3130,41 +3130,96 @@ static void intel_update_primary_planes(struct drm_device *dev)
>>>  
>>>  	for_each_crtc(dev, crtc) {
>>>  		struct intel_plane *plane = to_intel_plane(crtc->primary);
>>> -		struct intel_plane_state *plane_state;
>>> -
>>> -		drm_modeset_lock_crtc(crtc, &plane->base);
>>> -		plane_state = to_intel_plane_state(plane->base.state);
>>> +		struct intel_plane_state *plane_state =
>>> +			to_intel_plane_state(plane->base.state);
>>>  
>>>  		if (plane_state->visible)
>>>  			plane->update_plane(&plane->base,
>>>  					    to_intel_crtc_state(crtc->state),
>>>  					    plane_state);
>>> +	}
>>> +}
>>> +
>>> +static int
>>> +__intel_display_resume(struct drm_device *dev,
>>> +		       struct drm_atomic_state *state)
>>> +{
>>> +	struct drm_crtc_state *crtc_state;
>>> +	struct drm_crtc *crtc;
>>> +	int i, ret;
>>> +
>>> +	intel_modeset_setup_hw_state(dev);
>>> +	i915_redisable_vga(dev);
>>>  
>>> -		drm_modeset_unlock_crtc(crtc);
>>> +	if (!state)
>>> +		return 0;
>> Thank you diff for making things illegible.
>>
>> I'm still not convinced we should be changing the locking scheme
>> here, especially in what's supposed to be just a fix.
>>
>> In general, I'm not sure we want ->detect() and other irrelevant
>> stuff to block the GPU reset. The nice thing about g4x+ reset so
>> far has been that it's almost unnoticeable. Of course if it's a
>> genuine GPU hang the screen will probably have been frozen for
>> quite a while when we initiate the reset, so perhaps that's not
>> a huge real world issue.
> We don't really need dev->mode_config.mutex for atomic commits, so taking
> that out and use drm_modeset_lock_all_ctx would give you that.
> -Daniel

Except that i915 still complains if we don't hold mode_config.mutex

commit ea49c9acf2db7082f0406bb3a570cc6bad37082b
Author: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Date:   Tue Feb 16 15:27:42 2016 +0100

    drm/i915: Lock mode_config.mutex in intel_display_resume.

So keeping it for now would be better.

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v4.
  2016-05-10  7:48       ` Daniel Vetter
  2016-05-10 17:08         ` Maarten Lankhorst
@ 2016-05-11  8:35         ` Maarten Lankhorst
  1 sibling, 0 replies; 10+ messages in thread
From: Maarten Lankhorst @ 2016-05-11  8:35 UTC (permalink / raw)
  To: Daniel Vetter, Ville Syrjälä; +Cc: intel-gfx, drm-intel-fixes

Op 10-05-16 om 09:48 schreef Daniel Vetter:
> On Mon, May 09, 2016 at 03:54:15PM +0300, Ville Syrjälä wrote:
>> On Mon, May 09, 2016 at 01:04:21PM +0200, Maarten Lankhorst wrote:
>>> This function would call drm_modeset_lock_all, while the suspend/resume
>>> functions already have their own locking. Fix this by factoring out
>>> __intel_display_resume, and calling the atomic helpers for duplicating
>>> atomic state and disabling all crtc's during suspend.
>>>
>>> Changes since v1:
>>> - Deal with -EDEADLK right after lock_all and clean up calls
>>>   to hw readout.
>>> - Always take all modeset locks so updates during gpu reset are blocked.
>>> Changes since v2:
>>> - Fix deadlock in intel_update_primary_planes.
>>> - Move WARN_ON(EDEADLK) to __intel_display_resume.
>>> - pctx -> ctx
>>> - only call __intel_display_resume on success in intel_display_resume.
>>>
>>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
>>> Cc: drm-intel-fixes@lists.freedesktop.org
>>> ---
>>>  drivers/gpu/drm/i915/intel_display.c | 150 ++++++++++++++++++++++-------------
>>>  1 file changed, 93 insertions(+), 57 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 14e05091c397..6faa529f35df 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -3130,41 +3130,96 @@ static void intel_update_primary_planes(struct drm_device *dev)
>>>  
>>>  	for_each_crtc(dev, crtc) {
>>>  		struct intel_plane *plane = to_intel_plane(crtc->primary);
>>> -		struct intel_plane_state *plane_state;
>>> -
>>> -		drm_modeset_lock_crtc(crtc, &plane->base);
>>> -		plane_state = to_intel_plane_state(plane->base.state);
>>> +		struct intel_plane_state *plane_state =
>>> +			to_intel_plane_state(plane->base.state);
>>>  
>>>  		if (plane_state->visible)
>>>  			plane->update_plane(&plane->base,
>>>  					    to_intel_crtc_state(crtc->state),
>>>  					    plane_state);
>>> +	}
>>> +}
>>> +
>>> +static int
>>> +__intel_display_resume(struct drm_device *dev,
>>> +		       struct drm_atomic_state *state)
>>> +{
>>> +	struct drm_crtc_state *crtc_state;
>>> +	struct drm_crtc *crtc;
>>> +	int i, ret;
>>> +
>>> +	intel_modeset_setup_hw_state(dev);
>>> +	i915_redisable_vga(dev);
>>>  
>>> -		drm_modeset_unlock_crtc(crtc);
>>> +	if (!state)
>>> +		return 0;
>> Thank you diff for making things illegible.
>>
>> I'm still not convinced we should be changing the locking scheme
>> here, especially in what's supposed to be just a fix.
>>
>> In general, I'm not sure we want ->detect() and other irrelevant
>> stuff to block the GPU reset. The nice thing about g4x+ reset so
>> far has been that it's almost unnoticeable. Of course if it's a
>> genuine GPU hang the screen will probably have been frozen for
>> quite a while when we initiate the reset, so perhaps that's not
>> a huge real world issue.
> We don't really need dev->mode_config.mutex for atomic commits, so taking
> that out and use drm_modeset_lock_all_ctx would give you that.
> -Daniel

---->8----

This function would call drm_modeset_lock_all, while the suspend/resume
functions already have their own locking. Fix this by factoring out
__intel_display_resume, and calling the atomic helpers for duplicating
atomic state and disabling all crtc's during suspend.

Changes since v1:
- Deal with -EDEADLK right after lock_all and clean up calls
  to hw readout.
- Always take all modeset locks so updates during gpu reset are blocked.
Changes since v2:
- Fix deadlock in intel_update_primary_planes.
- Move WARN_ON(EDEADLK) to __intel_display_resume.
- pctx -> ctx
- only call __intel_display_resume on success in intel_display_resume.
Changes since v3:
- Rebase on top of dev_priv -> dev change.
- Use drm_modeset_lock_all_ctx instead of drm_modeset_lock_all.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.")
Cc: drm-intel-fixes@lists.freedesktop.org
---
 drivers/gpu/drm/i915/i915_drv.h      |   1 +
 drivers/gpu/drm/i915/intel_display.c | 164 +++++++++++++++++++++++------------
 2 files changed, 109 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4abd39f32c0f..422e551937f7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1835,6 +1835,7 @@ struct drm_i915_private {
 	enum modeset_restore modeset_restore;
 	struct mutex modeset_restore_lock;
 	struct drm_atomic_state *modeset_restore_state;
+	struct drm_modeset_acquire_ctx reset_ctx;
 
 	struct list_head vm_list; /* Global list of all address spaces */
 	struct i915_ggtt ggtt; /* VM representing the global address space */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 138ed1aa3938..e88a942787c5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3130,40 +3130,109 @@ static void intel_update_primary_planes(struct drm_device *dev)
 
 	for_each_crtc(dev, crtc) {
 		struct intel_plane *plane = to_intel_plane(crtc->primary);
-		struct intel_plane_state *plane_state;
-
-		drm_modeset_lock_crtc(crtc, &plane->base);
-		plane_state = to_intel_plane_state(plane->base.state);
+		struct intel_plane_state *plane_state =
+			to_intel_plane_state(plane->base.state);
 
 		if (plane_state->visible)
 			plane->update_plane(&plane->base,
 					    to_intel_crtc_state(crtc->state),
 					    plane_state);
+	}
+}
+
+static int
+__intel_display_resume(struct drm_device *dev,
+		       struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	intel_modeset_setup_hw_state(dev);
+	i915_redisable_vga(dev);
 
-		drm_modeset_unlock_crtc(crtc);
+	if (!state)
+		return 0;
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		/*
+		 * Force recalculation even if we restore
+		 * current state. With fast modeset this may not result
+		 * in a modeset when the state is compatible.
+		 */
+		crtc_state->mode_changed = true;
 	}
+
+	ret = drm_atomic_commit(state);
+
+	WARN_ON(ret == -EDEADLK);
+	return ret;
 }
 
 void intel_prepare_reset(struct drm_i915_private *dev_priv)
 {
+	struct drm_atomic_state *state;
+	struct drm_modeset_acquire_ctx *ctx;
+	int ret;
+
 	/* no reset support for gen2 */
 	if (IS_GEN2(dev_priv))
 		return;
 
-	/* reset doesn't touch the display */
+	ctx = &dev_priv->reset_ctx;
+
+	/*
+	 * This is a cludge because with real atomic modeset mode_config.mutex
+	 * won't be taken. Unfortunately some probed state like
+	 * audio_codec_enable is still protected by mode_config.mutex, so lock
+	 * it here for now.
+	 */
+	mutex_lock(&dev_priv->dev->mode_config.mutex);
+	drm_modeset_acquire_init(ctx, 0);
+	while (1) {
+		ret = drm_modeset_lock_all_ctx(dev_priv->dev, ctx);
+		if (ret != -EDEADLK)
+			break;
+
+		drm_modeset_backoff(ctx);
+	}
+
+	/* reset doesn't touch the display, but flips might get nuked anyway, */
 	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		return;
 
-	drm_modeset_lock_all(dev_priv->dev);
 	/*
 	 * Disabling the crtcs gracefully seems nicer. Also the
 	 * g33 docs say we should at least disable all the planes.
 	 */
-	intel_display_suspend(dev_priv->dev);
+	state = drm_atomic_helper_duplicate_state(dev_priv->dev, ctx);
+	if (IS_ERR(state)) {
+		ret = PTR_ERR(state);
+		state = NULL;
+		DRM_ERROR("Duplicating state failed with %i\n", ret);
+		goto err;
+	}
+
+	ret = drm_atomic_helper_disable_all(dev_priv->dev, ctx);
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		goto err;
+	}
+
+	dev_priv->modeset_restore_state = state;
+	state->acquire_ctx = ctx;
+	return;
+
+err:
+	drm_atomic_state_free(state);
 }
 
 void intel_finish_reset(struct drm_i915_private *dev_priv)
 {
+	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
+	struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx;
+	int ret;
+
 	/*
 	 * Flips in the rings will be nuked by the reset,
 	 * so complete all pending flips so that user space
@@ -3175,6 +3244,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
 	if (IS_GEN2(dev_priv))
 		return;
 
+	dev_priv->modeset_restore_state = NULL;
+
 	/* reset doesn't touch the display */
 	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
 		/*
@@ -3187,28 +3258,31 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
 		 * CS-based flips (which might get lost in gpu resets) any more.
 		 */
 		intel_update_primary_planes(dev_priv->dev);
-		return;
-	}
-
-	/*
-	 * The display has been reset as well,
-	 * so need a full re-initialization.
-	 */
-	intel_runtime_pm_disable_interrupts(dev_priv);
-	intel_runtime_pm_enable_interrupts(dev_priv);
+	} else {
+		/*
+		* The display has been reset as well,
+		* so need a full re-initialization.
+		*/
+		intel_runtime_pm_disable_interrupts(dev_priv);
+		intel_runtime_pm_enable_interrupts(dev_priv);
 
-	intel_modeset_init_hw(dev_priv->dev);
+		intel_modeset_init_hw(dev_priv->dev);
 
-	spin_lock_irq(&dev_priv->irq_lock);
-	if (dev_priv->display.hpd_irq_setup)
-		dev_priv->display.hpd_irq_setup(dev_priv);
-	spin_unlock_irq(&dev_priv->irq_lock);
+		spin_lock_irq(&dev_priv->irq_lock);
+		if (dev_priv->display.hpd_irq_setup)
+			dev_priv->display.hpd_irq_setup(dev_priv);
+		spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_display_resume(dev_priv->dev);
+		ret = __intel_display_resume(dev_priv->dev, state);
+		if (ret)
+			DRM_ERROR("Restoring old state failed with %i\n", ret);
 
-	intel_hpd_init(dev_priv);
+		intel_hpd_init(dev_priv);
+	}
 
-	drm_modeset_unlock_all(dev_priv->dev);
+	drm_modeset_drop_locks(ctx);
+	drm_modeset_acquire_fini(ctx);
+	mutex_unlock(&dev_priv->dev->mode_config.mutex);
 }
 
 static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
@@ -15957,9 +16031,10 @@ void intel_display_resume(struct drm_device *dev)
 	struct drm_atomic_state *state = dev_priv->modeset_restore_state;
 	struct drm_modeset_acquire_ctx ctx;
 	int ret;
-	bool setup = false;
 
 	dev_priv->modeset_restore_state = NULL;
+	if (state)
+		state->acquire_ctx = &ctx;
 
 	/*
 	 * This is a cludge because with real atomic modeset mode_config.mutex
@@ -15970,40 +16045,17 @@ void intel_display_resume(struct drm_device *dev)
 	mutex_lock(&dev->mode_config.mutex);
 	drm_modeset_acquire_init(&ctx, 0);
 
-retry:
-	ret = drm_modeset_lock_all_ctx(dev, &ctx);
-
-	if (ret == 0 && !setup) {
-		setup = true;
-
-		intel_modeset_setup_hw_state(dev);
-		i915_redisable_vga(dev);
-	}
-
-	if (ret == 0 && state) {
-		struct drm_crtc_state *crtc_state;
-		struct drm_crtc *crtc;
-		int i;
-
-		state->acquire_ctx = &ctx;
-
-		for_each_crtc_in_state(state, crtc, crtc_state, i) {
-			/*
-			 * Force recalculation even if we restore
-			 * current state. With fast modeset this may not result
-			 * in a modeset when the state is compatible.
-			 */
-			crtc_state->mode_changed = true;
-		}
-
-		ret = drm_atomic_commit(state);
-	}
+	while (1) {
+		ret = drm_modeset_lock_all_ctx(dev, &ctx);
+		if (ret != -EDEADLK)
+			break;
 
-	if (ret == -EDEADLK) {
 		drm_modeset_backoff(&ctx);
-		goto retry;
 	}
 
+	if (!ret)
+		ret = __intel_display_resume(dev, state);
+
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 	mutex_unlock(&dev->mode_config.mutex);
-- 
2.5.5


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-05-11  8:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-02  8:57 [PATCH 1/2] drm/i915: Fix modeset handling during gpu reset, v2 Maarten Lankhorst
2016-05-02  8:57 ` [PATCH 2/2] drm/i915: Add a way to test the modeset done during gpu reset, v3 Maarten Lankhorst
2016-05-02  9:59 ` ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/i915: Fix modeset handling during gpu reset, v2 Patchwork
2016-05-06 13:06 ` [PATCH 1/2] " Ville Syrjälä
2016-05-09 10:29   ` Maarten Lankhorst
2016-05-09 11:04   ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v3 Maarten Lankhorst
2016-05-09 12:54     ` Ville Syrjälä
2016-05-10  7:48       ` Daniel Vetter
2016-05-10 17:08         ` Maarten Lankhorst
2016-05-11  8:35         ` [PATCH v3 1/2] drm/i915: Fix modeset handling during gpu reset, v4 Maarten Lankhorst

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.