* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox