* [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock
2017-07-20 11:43 [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
@ 2017-07-20 11:43 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 11:43 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Mika Kuoppala, Daniel Vetter
There's no reason to entirely wedge the gpu, for the minimal deadlock
bugfix we only need to unbreak/decouple the atomic commit from the gpu
reset. The simplest way to fix that is by replacing the
unconditional fence wait a the top of commit_tail by a wait which
completes either when the fences are done (normal case, or when a
reset doesn't need to touch the display state). Or when the gpu reset
needs to force-unblock all pending modeset states.
The lesser source of deadlocks is when we try to pin a new framebuffer
and run into a stall. There's a bunch of places this can happen, like
eviction, changing the caching mode, acquiring a fence on older
platforms. And we can't just break the depency loop and keep going,
the only way would be to break out and restart. But the problem with
that approach is that we must stall for the reset to complete before
we grab any locks, and with the atomic infrastructure that's a bit
tricky. The only place is the ioctl code, and we don't want to insert
code into e.g. the BUSY ioctl. Hence for that problem just create a
critical section, and if any code is in there, wedge the GPU. For the
steady-state this should never be a problem.
Note that in both cases TDR itself keeps working, so from a userspace
pov this trickery isn't observable. Users themselvs might spot a short
glitch while the rendering is catching up again, but that's still
better than pre-TDR where we've thrown away all the rendering,
including innocent batches. Also, this fixes the regression TDR
introduced of making gpu resets deadlock-prone when we do need to
touch the display.
One thing I noticed is that gpu_error.flags seems to use both our own
wait-queue in gpu_error.wait_queue, and the generic wait_on_bit
facilities. Not entirely sure why this inconsistency exists, I just
picked one style.
A possible future avenue could be to insert the gpu reset in-between
ongoing modeset changes, which would avoid the momentary glitch. But
that's a lot more work to implement in the atomic commit machinery,
and given that we only need this for pre-g4x hw, of questionable
utility just for the sake of polishing gpu reset even more on those
old boxes. It might be useful for other features though.
v2: Rebase onto 4.13 with a s/wait_queue_t/struct wait_queue_entry/.
v3: Really emabarrassing fixup, I checked the wrong bit and broke the
unbreak/wakeup logic.
v4: Also handle deadlocks in pin_to_display.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 3 +++
drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++++++++++++++++-----
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 07e98b07c5bc..9b055deca36d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1505,6 +1505,8 @@ struct i915_gpu_error {
/* Protected by the above dev->gpu_error.lock. */
struct i915_gpu_state *first_error;
+ atomic_t pending_fb_pin;
+
unsigned long missed_irq_rings;
/**
@@ -1564,6 +1566,7 @@ struct i915_gpu_error {
unsigned long flags;
#define I915_RESET_BACKOFF 0
#define I915_RESET_HANDOFF 1
+#define I915_RESET_MODESET 2
#define I915_WEDGED (BITS_PER_LONG - 1)
#define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f6bd6282d7f7..63ea8d6b2ebd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2162,6 +2162,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
*/
intel_runtime_pm_get(dev_priv);
+ atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
+
vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
if (IS_ERR(vma))
goto err;
@@ -2189,6 +2191,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
i915_vma_get(vma);
err:
+ atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
+
intel_runtime_pm_put(dev_priv);
return vma;
}
@@ -3471,11 +3475,14 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
!gpu_reset_clobbers_display(dev_priv))
return;
- /* We have a modeset vs reset deadlock, defensively unbreak it.
- *
- * FIXME: We can do a _lot_ better, this is just a first iteration.*/
- i915_gem_set_wedged(dev_priv);
- DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
+ /* We have a modeset vs reset deadlock, defensively unbreak it. */
+ set_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
+ wake_up_all(&dev_priv->gpu_error.wait_queue);
+
+ if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
+ DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
+ i915_gem_set_wedged(dev_priv);
+ }
/*
* Need mode_config.mutex so that we don't
@@ -3570,6 +3577,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
mutex_unlock(&dev->mode_config.mutex);
+
+ clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
}
static bool abort_flip_on_reset(struct intel_crtc *crtc)
@@ -12381,6 +12390,30 @@ static void intel_atomic_helper_free_state_worker(struct work_struct *work)
intel_atomic_helper_free_state(dev_priv);
}
+static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
+{
+ struct wait_queue_entry wait_fence, wait_reset;
+ struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
+
+ init_wait_entry(&wait_fence, 0);
+ init_wait_entry(&wait_reset, 0);
+ for (;;) {
+ prepare_to_wait(&intel_state->commit_ready.wait,
+ &wait_fence, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(&dev_priv->gpu_error.wait_queue,
+ &wait_reset, TASK_UNINTERRUPTIBLE);
+
+
+ if (i915_sw_fence_done(&intel_state->commit_ready)
+ || test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags))
+ break;
+
+ schedule();
+ }
+ finish_wait(&intel_state->commit_ready.wait, &wait_fence);
+ finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
+}
+
static void intel_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
@@ -12394,7 +12427,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
unsigned crtc_vblank_mask = 0;
int i;
- i915_sw_fence_wait(&intel_state->commit_ready);
+ intel_atomic_commit_fence_wait(intel_state);
drm_atomic_helper_wait_for_dependencies(state);
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 0/7] gpu reset and page_flip removal, take 2
@ 2017-07-20 17:57 Daniel Vetter
2017-07-20 17:57 ` [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
` (7 more replies)
0 siblings, 8 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter
Hi all,
I landed the locking change, which fixes the gpu reset deadlocks at least for
anything modern (and non-igt). Would be great if we can get the first patch
landed fast, just to address the regression in CI and get rid of the dmesg-warn.
Currently we're blind to dmesg noise in a lot of gpu hang tests and that's not
all that good (the timeout based wedging has a DRM_ERROR, which I think is the
right thing for unexpected delays).
The remaining patches, especially patch 3, probably need a bunch more soaking
time. I think 4-7 are ready for merging, not much pointing in holding them up
due to lack of boosting in atomic.
As usual, review&testing very much welcome.
Thanks,
Daniel
Daniel Vetter (7):
drm/i915: Avoid the gpu reset vs. modeset deadlock
drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
drm/i915: More surgically unbreak the modeset vs reset deadlock
drm/i915: Rip out legacy page_flip completion/irq handling
drm/i915: adjust has_pending_fb_unpin to atomic
drm/i915: Remove intel_flip_work infrastructure
drm/i915: Drop unpin stall in atomic_prepare_commit
drivers/gpu/drm/i915/i915_debugfs.c | 70 ------
drivers/gpu/drm/i915/i915_drv.c | 1 -
drivers/gpu/drm/i915/i915_drv.h | 7 +-
drivers/gpu/drm/i915/i915_gem.c | 2 -
drivers/gpu/drm/i915/i915_irq.c | 151 ++-----------
drivers/gpu/drm/i915/intel_display.c | 424 +++++------------------------------
drivers/gpu/drm/i915/intel_drv.h | 26 +--
drivers/gpu/drm/i915/intel_sprite.c | 8 +-
8 files changed, 88 insertions(+), 601 deletions(-)
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-07-20 19:47 ` Chris Wilson
2017-07-20 17:57 ` [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit Daniel Vetter
` (6 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Mika Kuoppala, Daniel Vetter
... using the biggest hammer we have. This is essentially a weaponized
version of the timeout-based wedging Chris added in
commit 36703e79a982c8ce5a8e43833291f2719e92d0d1
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Thu Jun 22 11:56:25 2017 +0100
drm/i915: Break modeset deadlocks on reset
Because defense-in-depth is good it's good to still have both. Also
note that with the locking change we can now restrict this a lot (old
gpus and special testing only), so this doesn't kill the TDR benefits
on at least anything remotely modern.
And futuremore with a few tricks it should be possible to make a much
more educated guess about whether an atomic commit is stuck waiting on
the gpu (atomic_t counting the pending i915_sw_fence used by the
atomic modeset code should do it), so we can improve this.
But for now just start with something that is guaranteed to recover
faster, for much better CI througput.
This defacto reverts TDR on these platforms, but there's not really a
single commit to specify as the sole offender.
v2: Add a debug message to explain what's going on. We can't DRM_ERROR
because that spams CI. And the timeout based fallback still prints a
DRM_ERROR, in case something goes wrong.
Fixes: 4680816be336 ("drm/i915: Wait first for submission, before waiting for request completion")
Fixes: 221fe7994554 ("drm/i915: Perform a direct reset of the GPU from the waiter")
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 02b1f4966049..995522e40ec1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3471,6 +3471,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
!gpu_reset_clobbers_display(dev_priv))
return;
+ /* We have a modeset vs reset deadlock, defensively unbreak it.
+ *
+ * FIXME: We can do a _lot_ better, this is just a first iteration.*/
+ i915_gem_set_wedged(dev_priv);
+ DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
+
/*
* Need mode_config.mutex so that we don't
* trample ongoing ->detect() and whatnot.
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
2017-07-20 17:57 ` [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-08-03 19:44 ` Michel Thierry
2017-07-20 17:57 ` [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock Daniel Vetter
` (5 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Mika Kuoppala, Daniel Vetter
Blocking in a worker is ok, that's what the unbound_wq is for. And it
unifies the paths between the blocking and nonblocking commit, giving
me just one path where I have to implement the deadlock avoidance
trickery in the next patch.
I first tried to implement the following patch without this rework, but
force-completing i915_sw_fence creates some serious challenges around
properly cleaning things up. So wasn't a feasible short-term approach.
Another approach would be to simple keep track of all pending atomic
commit work items and manually queue them from the reset code. With the
caveat that double-queue in case we race with the i915_sw_fence must be
avoided. Given all that, taking the cost of a double schedule in atomic
for the short-term fix is the best approach, but can be changed in the
future of course.
v2: Amend commit message (Chris).
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 995522e40ec1..f6bd6282d7f7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12394,6 +12394,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
unsigned crtc_vblank_mask = 0;
int i;
+ i915_sw_fence_wait(&intel_state->commit_ready);
+
drm_atomic_helper_wait_for_dependencies(state);
if (intel_state->modeset)
@@ -12561,10 +12563,7 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
switch (notify) {
case FENCE_COMPLETE:
- if (state->base.commit_work.func)
- queue_work(system_unbound_wq, &state->base.commit_work);
break;
-
case FENCE_FREE:
{
struct intel_atomic_helper *helper =
@@ -12668,14 +12667,14 @@ static int intel_atomic_commit(struct drm_device *dev,
}
drm_atomic_state_get(state);
- INIT_WORK(&state->commit_work,
- nonblock ? intel_atomic_commit_work : NULL);
+ INIT_WORK(&state->commit_work, intel_atomic_commit_work);
i915_sw_fence_commit(&intel_state->commit_ready);
- if (!nonblock) {
- i915_sw_fence_wait(&intel_state->commit_ready);
+ if (nonblock)
+ queue_work(system_unbound_wq, &state->commit_work);
+ else
intel_atomic_commit_tail(state);
- }
+
return 0;
}
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
2017-07-20 17:57 ` [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
2017-07-20 17:57 ` [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-08-03 19:35 ` Michel Thierry
2017-07-20 17:57 ` [PATCH 4/7] drm/i915: Rip out legacy page_flip completion/irq handling Daniel Vetter
` (4 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Mika Kuoppala, Daniel Vetter
There's no reason to entirely wedge the gpu, for the minimal deadlock
bugfix we only need to unbreak/decouple the atomic commit from the gpu
reset. The simplest way to fix that is by replacing the
unconditional fence wait a the top of commit_tail by a wait which
completes either when the fences are done (normal case, or when a
reset doesn't need to touch the display state). Or when the gpu reset
needs to force-unblock all pending modeset states.
The lesser source of deadlocks is when we try to pin a new framebuffer
and run into a stall. There's a bunch of places this can happen, like
eviction, changing the caching mode, acquiring a fence on older
platforms. And we can't just break the depency loop and keep going,
the only way would be to break out and restart. But the problem with
that approach is that we must stall for the reset to complete before
we grab any locks, and with the atomic infrastructure that's a bit
tricky. The only place is the ioctl code, and we don't want to insert
code into e.g. the BUSY ioctl. Hence for that problem just create a
critical section, and if any code is in there, wedge the GPU. For the
steady-state this should never be a problem.
Note that in both cases TDR itself keeps working, so from a userspace
pov this trickery isn't observable. Users themselvs might spot a short
glitch while the rendering is catching up again, but that's still
better than pre-TDR where we've thrown away all the rendering,
including innocent batches. Also, this fixes the regression TDR
introduced of making gpu resets deadlock-prone when we do need to
touch the display.
One thing I noticed is that gpu_error.flags seems to use both our own
wait-queue in gpu_error.wait_queue, and the generic wait_on_bit
facilities. Not entirely sure why this inconsistency exists, I just
picked one style.
A possible future avenue could be to insert the gpu reset in-between
ongoing modeset changes, which would avoid the momentary glitch. But
that's a lot more work to implement in the atomic commit machinery,
and given that we only need this for pre-g4x hw, of questionable
utility just for the sake of polishing gpu reset even more on those
old boxes. It might be useful for other features though.
v2: Rebase onto 4.13 with a s/wait_queue_t/struct wait_queue_entry/.
v3: Really emabarrassing fixup, I checked the wrong bit and broke the
unbreak/wakeup logic.
v4: Also handle deadlocks in pin_to_display.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 3 +++
drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++++++++++++++++-----
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 07e98b07c5bc..9b055deca36d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1505,6 +1505,8 @@ struct i915_gpu_error {
/* Protected by the above dev->gpu_error.lock. */
struct i915_gpu_state *first_error;
+ atomic_t pending_fb_pin;
+
unsigned long missed_irq_rings;
/**
@@ -1564,6 +1566,7 @@ struct i915_gpu_error {
unsigned long flags;
#define I915_RESET_BACKOFF 0
#define I915_RESET_HANDOFF 1
+#define I915_RESET_MODESET 2
#define I915_WEDGED (BITS_PER_LONG - 1)
#define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f6bd6282d7f7..63ea8d6b2ebd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2162,6 +2162,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
*/
intel_runtime_pm_get(dev_priv);
+ atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
+
vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
if (IS_ERR(vma))
goto err;
@@ -2189,6 +2191,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
i915_vma_get(vma);
err:
+ atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
+
intel_runtime_pm_put(dev_priv);
return vma;
}
@@ -3471,11 +3475,14 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
!gpu_reset_clobbers_display(dev_priv))
return;
- /* We have a modeset vs reset deadlock, defensively unbreak it.
- *
- * FIXME: We can do a _lot_ better, this is just a first iteration.*/
- i915_gem_set_wedged(dev_priv);
- DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
+ /* We have a modeset vs reset deadlock, defensively unbreak it. */
+ set_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
+ wake_up_all(&dev_priv->gpu_error.wait_queue);
+
+ if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
+ DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
+ i915_gem_set_wedged(dev_priv);
+ }
/*
* Need mode_config.mutex so that we don't
@@ -3570,6 +3577,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
drm_modeset_drop_locks(ctx);
drm_modeset_acquire_fini(ctx);
mutex_unlock(&dev->mode_config.mutex);
+
+ clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
}
static bool abort_flip_on_reset(struct intel_crtc *crtc)
@@ -12381,6 +12390,30 @@ static void intel_atomic_helper_free_state_worker(struct work_struct *work)
intel_atomic_helper_free_state(dev_priv);
}
+static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
+{
+ struct wait_queue_entry wait_fence, wait_reset;
+ struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
+
+ init_wait_entry(&wait_fence, 0);
+ init_wait_entry(&wait_reset, 0);
+ for (;;) {
+ prepare_to_wait(&intel_state->commit_ready.wait,
+ &wait_fence, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(&dev_priv->gpu_error.wait_queue,
+ &wait_reset, TASK_UNINTERRUPTIBLE);
+
+
+ if (i915_sw_fence_done(&intel_state->commit_ready)
+ || test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags))
+ break;
+
+ schedule();
+ }
+ finish_wait(&intel_state->commit_ready.wait, &wait_fence);
+ finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
+}
+
static void intel_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
@@ -12394,7 +12427,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
unsigned crtc_vblank_mask = 0;
int i;
- i915_sw_fence_wait(&intel_state->commit_ready);
+ intel_atomic_commit_fence_wait(intel_state);
drm_atomic_helper_wait_for_dependencies(state);
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/7] drm/i915: Rip out legacy page_flip completion/irq handling
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
` (2 preceding siblings ...)
2017-07-20 17:57 ` [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-07-20 17:57 ` [PATCH 5/7] drm/i915: adjust has_pending_fb_unpin to atomic Daniel Vetter
` (3 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Daniel Vetter
All these races and things are now solved through the vblank evasion
trick, plus event handling is done using normal vblank even processing
and drm_crtc_arm_vblank_event. We can get rid of all this complexity.
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/i915_irq.c | 151 ++++--------------------
drivers/gpu/drm/i915/intel_display.c | 215 -----------------------------------
drivers/gpu/drm/i915/intel_drv.h | 3 -
3 files changed, 22 insertions(+), 347 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f0cb278cee8b..b64c89e0fbf1 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1708,18 +1708,6 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
}
}
-static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv,
- enum pipe pipe)
-{
- bool ret;
-
- ret = drm_handle_vblank(&dev_priv->drm, pipe);
- if (ret)
- intel_finish_page_flip_mmio(dev_priv, pipe);
-
- return ret;
-}
-
static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
{
@@ -1784,12 +1772,8 @@ static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
- intel_pipe_handle_vblank(dev_priv, pipe))
- intel_check_page_flip(dev_priv, pipe);
-
- if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
- intel_finish_page_flip_cs(dev_priv, pipe);
+ if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev_priv, pipe);
@@ -2241,19 +2225,14 @@ static void ilk_display_irq_handler(struct drm_i915_private *dev_priv,
DRM_ERROR("Poison interrupt\n");
for_each_pipe(dev_priv, pipe) {
- if (de_iir & DE_PIPE_VBLANK(pipe) &&
- intel_pipe_handle_vblank(dev_priv, pipe))
- intel_check_page_flip(dev_priv, pipe);
+ if (de_iir & DE_PIPE_VBLANK(pipe))
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
if (de_iir & DE_PIPE_CRC_DONE(pipe))
i9xx_pipe_crc_irq_handler(dev_priv, pipe);
-
- /* plane/pipes map 1:1 on ilk+ */
- if (de_iir & DE_PLANE_FLIP_DONE(pipe))
- intel_finish_page_flip_cs(dev_priv, pipe);
}
/* check event from PCH */
@@ -2315,13 +2294,8 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
intel_opregion_asle_intr(dev_priv);
for_each_pipe(dev_priv, pipe) {
- if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)) &&
- intel_pipe_handle_vblank(dev_priv, pipe))
- intel_check_page_flip(dev_priv, pipe);
-
- /* plane/pipes map 1:1 on ilk+ */
- if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
- intel_finish_page_flip_cs(dev_priv, pipe);
+ if (de_iir & (DE_PIPE_VBLANK_IVB(pipe)))
+ drm_handle_vblank(&dev_priv->drm, pipe);
}
/* check event from PCH */
@@ -2502,7 +2476,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
}
for_each_pipe(dev_priv, pipe) {
- u32 flip_done, fault_errors;
+ u32 fault_errors;
if (!(master_ctl & GEN8_DE_PIPE_IRQ(pipe)))
continue;
@@ -2516,18 +2490,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
ret = IRQ_HANDLED;
I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir);
- if (iir & GEN8_PIPE_VBLANK &&
- intel_pipe_handle_vblank(dev_priv, pipe))
- intel_check_page_flip(dev_priv, pipe);
-
- flip_done = iir;
- if (INTEL_INFO(dev_priv)->gen >= 9)
- flip_done &= GEN9_PIPE_PLANE1_FLIP_DONE;
- else
- flip_done &= GEN8_PIPE_PRIMARY_FLIP_DONE;
-
- if (flip_done)
- intel_finish_page_flip_cs(dev_priv, pipe);
+ if (iir & GEN8_PIPE_VBLANK)
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
hsw_pipe_crc_irq_handler(dev_priv, pipe);
@@ -3710,34 +3674,6 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
/*
* Returns true when a page flip has completed.
*/
-static bool i8xx_handle_vblank(struct drm_i915_private *dev_priv,
- int plane, int pipe, u32 iir)
-{
- u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
-
- if (!intel_pipe_handle_vblank(dev_priv, pipe))
- return false;
-
- if ((iir & flip_pending) == 0)
- goto check_page_flip;
-
- /* We detect FlipDone by looking for the change in PendingFlip from '1'
- * to '0' on the following vblank, i.e. IIR has the Pendingflip
- * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
- * the flip is completed (no longer pending). Since this doesn't raise
- * an interrupt per se, we watch for the change at vblank.
- */
- if (I915_READ16(ISR) & flip_pending)
- goto check_page_flip;
-
- intel_finish_page_flip_cs(dev_priv, pipe);
- return true;
-
-check_page_flip:
- intel_check_page_flip(dev_priv, pipe);
- return false;
-}
-
static irqreturn_t i8xx_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
@@ -3745,9 +3681,6 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
u16 iir, new_iir;
u32 pipe_stats[2];
int pipe;
- u16 flip_mask =
- I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
- I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
irqreturn_t ret;
if (!intel_irqs_enabled(dev_priv))
@@ -3761,7 +3694,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
if (iir == 0)
goto out;
- while (iir & ~flip_mask) {
+ while (iir) {
/* Can't rely on pipestat interrupt bit in iir as it might
* have been cleared after the pipestat interrupt was received.
* It doesn't set the bit in iir again, but it still produces
@@ -3783,7 +3716,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
}
spin_unlock(&dev_priv->irq_lock);
- I915_WRITE16(IIR, iir & ~flip_mask);
+ I915_WRITE16(IIR, iir);
new_iir = I915_READ16(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
@@ -3794,9 +3727,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
if (HAS_FBC(dev_priv))
plane = !plane;
- if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
- i8xx_handle_vblank(dev_priv, plane, pipe, iir))
- flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
+ if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev_priv, pipe);
@@ -3896,45 +3828,11 @@ static int i915_irq_postinstall(struct drm_device *dev)
return 0;
}
-/*
- * Returns true when a page flip has completed.
- */
-static bool i915_handle_vblank(struct drm_i915_private *dev_priv,
- int plane, int pipe, u32 iir)
-{
- u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
-
- if (!intel_pipe_handle_vblank(dev_priv, pipe))
- return false;
-
- if ((iir & flip_pending) == 0)
- goto check_page_flip;
-
- /* We detect FlipDone by looking for the change in PendingFlip from '1'
- * to '0' on the following vblank, i.e. IIR has the Pendingflip
- * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
- * the flip is completed (no longer pending). Since this doesn't raise
- * an interrupt per se, we watch for the change at vblank.
- */
- if (I915_READ(ISR) & flip_pending)
- goto check_page_flip;
-
- intel_finish_page_flip_cs(dev_priv, pipe);
- return true;
-
-check_page_flip:
- intel_check_page_flip(dev_priv, pipe);
- return false;
-}
-
static irqreturn_t i915_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
struct drm_i915_private *dev_priv = to_i915(dev);
u32 iir, new_iir, pipe_stats[I915_MAX_PIPES];
- u32 flip_mask =
- I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
- I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
int pipe, ret = IRQ_NONE;
if (!intel_irqs_enabled(dev_priv))
@@ -3945,7 +3843,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
iir = I915_READ(IIR);
do {
- bool irq_received = (iir & ~flip_mask) != 0;
+ bool irq_received = (iir) != 0;
bool blc_event = false;
/* Can't rely on pipestat interrupt bit in iir as it might
@@ -3980,7 +3878,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
i9xx_hpd_irq_handler(dev_priv, hotplug_status);
}
- I915_WRITE(IIR, iir & ~flip_mask);
+ I915_WRITE(IIR, iir);
new_iir = I915_READ(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
@@ -3991,9 +3889,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
if (HAS_FBC(dev_priv))
plane = !plane;
- if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
- i915_handle_vblank(dev_priv, plane, pipe, iir))
- flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
+ if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
blc_event = true;
@@ -4026,7 +3923,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
*/
ret = IRQ_HANDLED;
iir = new_iir;
- } while (iir & ~flip_mask);
+ } while (iir);
enable_rpm_wakeref_asserts(dev_priv);
@@ -4161,9 +4058,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
u32 iir, new_iir;
u32 pipe_stats[I915_MAX_PIPES];
int ret = IRQ_NONE, pipe;
- u32 flip_mask =
- I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
- I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
if (!intel_irqs_enabled(dev_priv))
return IRQ_NONE;
@@ -4174,7 +4068,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
iir = I915_READ(IIR);
for (;;) {
- bool irq_received = (iir & ~flip_mask) != 0;
+ bool irq_received = (iir) != 0;
bool blc_event = false;
/* Can't rely on pipestat interrupt bit in iir as it might
@@ -4212,7 +4106,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
i9xx_hpd_irq_handler(dev_priv, hotplug_status);
}
- I915_WRITE(IIR, iir & ~flip_mask);
+ I915_WRITE(IIR, iir);
new_iir = I915_READ(IIR); /* Flush posted writes */
if (iir & I915_USER_INTERRUPT)
@@ -4221,9 +4115,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
notify_ring(dev_priv->engine[VCS]);
for_each_pipe(dev_priv, pipe) {
- if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
- i915_handle_vblank(dev_priv, pipe, pipe, iir))
- flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
+ if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS)
+ drm_handle_vblank(&dev_priv->drm, pipe);
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
blc_event = true;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 63ea8d6b2ebd..fcbd4b7fa96c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3409,14 +3409,6 @@ static void skylake_disable_primary_plane(struct intel_plane *primary,
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
-static void intel_complete_page_flips(struct drm_i915_private *dev_priv)
-{
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(&dev_priv->drm, crtc)
- intel_finish_page_flip_cs(dev_priv, crtc->pipe);
-}
-
static int
__intel_display_resume(struct drm_device *dev,
struct drm_atomic_state *state,
@@ -3534,13 +3526,6 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
if (!state)
goto unlock;
- /*
- * Flips in the rings will be nuked by the reset,
- * so complete all pending flips so that user space
- * will get its events and not get stuck.
- */
- intel_complete_page_flips(dev_priv);
-
dev_priv->modeset_restore_state = NULL;
/* reset doesn't touch the display */
@@ -10136,140 +10121,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
kfree(intel_crtc);
}
-/* Is 'a' after or equal to 'b'? */
-static bool g4x_flip_count_after_eq(u32 a, u32 b)
-{
- return !((a - b) & 0x80000000);
-}
-
-static bool __pageflip_finished_cs(struct intel_crtc *crtc,
- struct intel_flip_work *work)
-{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (abort_flip_on_reset(crtc))
- return true;
-
- /*
- * The relevant registers doen't exist on pre-ctg.
- * As the flip done interrupt doesn't trigger for mmio
- * flips on gmch platforms, a flip count check isn't
- * really needed there. But since ctg has the registers,
- * include it in the check anyway.
- */
- if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
- return true;
-
- /*
- * BDW signals flip done immediately if the plane
- * is disabled, even if the plane enable is already
- * armed to occur at the next vblank :(
- */
-
- /*
- * A DSPSURFLIVE check isn't enough in case the mmio and CS flips
- * used the same base address. In that case the mmio flip might
- * have completed, but the CS hasn't even executed the flip yet.
- *
- * A flip count check isn't enough as the CS might have updated
- * the base address just after start of vblank, but before we
- * managed to process the interrupt. This means we'd complete the
- * CS flip too soon.
- *
- * Combining both checks should get us a good enough result. It may
- * still happen that the CS flip has been executed, but has not
- * yet actually completed. But in case the base address is the same
- * anyway, we don't really care.
- */
- return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
- crtc->flip_work->gtt_offset &&
- g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_G4X(crtc->pipe)),
- crtc->flip_work->flip_count);
-}
-
-static bool
-__pageflip_finished_mmio(struct intel_crtc *crtc,
- struct intel_flip_work *work)
-{
- /*
- * MMIO work completes when vblank is different from
- * flip_queued_vblank.
- *
- * Reset counter value doesn't matter, this is handled by
- * i915_wait_request finishing early, so no need to handle
- * reset here.
- */
- return intel_crtc_get_vblank_counter(crtc) != work->flip_queued_vblank;
-}
-
-
-static bool pageflip_finished(struct intel_crtc *crtc,
- struct intel_flip_work *work)
-{
- if (!atomic_read(&work->pending))
- return false;
-
- smp_rmb();
-
- if (is_mmio_work(work))
- return __pageflip_finished_mmio(crtc, work);
- else
- return __pageflip_finished_cs(crtc, work);
-}
-
-void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
-{
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
- struct intel_flip_work *work;
- unsigned long flags;
-
- /* Ignore early vblank irqs */
- if (!crtc)
- return;
-
- /*
- * This is called both by irq handlers and the reset code (to complete
- * lost pageflips) so needs the full irqsave spinlocks.
- */
- spin_lock_irqsave(&dev->event_lock, flags);
- work = crtc->flip_work;
-
- if (work != NULL &&
- !is_mmio_work(work) &&
- pageflip_finished(crtc, work))
- page_flip_completed(crtc);
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
-{
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
- struct intel_flip_work *work;
- unsigned long flags;
-
- /* Ignore early vblank irqs */
- if (!crtc)
- return;
-
- /*
- * This is called both by irq handlers and the reset code (to complete
- * lost pageflips) so needs the full irqsave spinlocks.
- */
- spin_lock_irqsave(&dev->event_lock, flags);
- work = crtc->flip_work;
-
- if (work != NULL &&
- is_mmio_work(work) &&
- pageflip_finished(crtc, work))
- page_flip_completed(crtc);
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
static inline void intel_mark_page_flip_active(struct intel_crtc *crtc,
struct intel_flip_work *work)
{
@@ -10280,72 +10131,6 @@ static inline void intel_mark_page_flip_active(struct intel_crtc *crtc,
atomic_set(&work->pending, 1);
}
-static bool __pageflip_stall_check_cs(struct drm_i915_private *dev_priv,
- struct intel_crtc *intel_crtc,
- struct intel_flip_work *work)
-{
- u32 addr, vblank;
-
- if (!atomic_read(&work->pending))
- return false;
-
- smp_rmb();
-
- vblank = intel_crtc_get_vblank_counter(intel_crtc);
- if (work->flip_ready_vblank == 0) {
- if (work->flip_queued_req &&
- !i915_gem_request_completed(work->flip_queued_req))
- return false;
-
- work->flip_ready_vblank = vblank;
- }
-
- if (vblank - work->flip_ready_vblank < 3)
- return false;
-
- /* Potential stall - if we see that the flip has happened,
- * assume a missed interrupt. */
- if (INTEL_GEN(dev_priv) >= 4)
- addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane)));
- else
- addr = I915_READ(DSPADDR(intel_crtc->plane));
-
- /* There is a potential issue here with a false positive after a flip
- * to the same address. We could address this by checking for a
- * non-incrementing frame counter.
- */
- return addr == work->gtt_offset;
-}
-
-void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
-{
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
- struct intel_flip_work *work;
-
- WARN_ON(!in_interrupt());
-
- if (crtc == NULL)
- return;
-
- spin_lock(&dev->event_lock);
- work = crtc->flip_work;
-
- if (work != NULL && !is_mmio_work(work) &&
- __pageflip_stall_check_cs(dev_priv, crtc, work)) {
- WARN_ONCE(1,
- "Kicking stuck page flip: queued at %d, now %d\n",
- work->flip_queued_vblank, intel_crtc_get_vblank_counter(crtc));
- page_flip_completed(crtc);
- work = NULL;
- }
-
- if (work != NULL && !is_mmio_work(work) &&
- intel_crtc_get_vblank_counter(crtc) - work->flip_queued_vblank > 1)
- intel_queue_rps_boost_for_request(work->flip_queued_req);
- spin_unlock(&dev->event_lock);
-}
-
/**
* intel_wm_need_update - Check whether watermarks need updating
* @plane: drm plane
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a8834daf5c07..04f80b013db9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1408,9 +1408,6 @@ void intel_unpin_fb_vma(struct i915_vma *vma);
struct drm_framebuffer *
intel_framebuffer_create(struct drm_i915_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
-void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe);
-void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe);
-void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe);
int intel_prepare_plane_fb(struct drm_plane *plane,
struct drm_plane_state *new_state);
void intel_cleanup_plane_fb(struct drm_plane *plane,
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 5/7] drm/i915: adjust has_pending_fb_unpin to atomic
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
` (3 preceding siblings ...)
2017-07-20 17:57 ` [PATCH 4/7] drm/i915: Rip out legacy page_flip completion/irq handling Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-07-20 17:57 ` [PATCH 6/7] drm/i915: Remove intel_flip_work infrastructure Daniel Vetter
` (2 subsequent siblings)
7 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter
A bit an oversight - the current code did nothing, since only
legacy flips used the unpin_work_count and assorted logic.
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/i915/intel_display.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fcbd4b7fa96c..bd0488a72503 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4149,21 +4149,22 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv)
{
- struct intel_crtc *crtc;
-
- /* Note that we don't need to be called with mode_config.lock here
- * as our list of CRTC objects is static for the lifetime of the
- * device and so cannot disappear as we iterate. Similarly, we can
- * happily treat the predicates as racy, atomic checks as userspace
- * cannot claim and pin a new fb without at least acquring the
- * struct_mutex and so serialising with us.
- */
- for_each_intel_crtc(&dev_priv->drm, crtc) {
- if (atomic_read(&crtc->unpin_work_count) == 0)
+ struct drm_crtc *crtc;
+ bool cleanup_done;
+
+ drm_for_each_crtc(crtc, &dev_priv->drm) {
+ struct drm_crtc_commit *commit;
+ spin_lock(&crtc->commit_lock);
+ commit = list_first_entry_or_null(&crtc->commit_list,
+ struct drm_crtc_commit, commit_entry);
+ cleanup_done = commit ?
+ try_wait_for_completion(&commit->cleanup_done) : true;
+ spin_unlock(&crtc->commit_lock);
+
+ if (cleanup_done)
continue;
- if (crtc->flip_work)
- intel_wait_for_vblank(dev_priv, crtc->pipe);
+ drm_crtc_wait_one_vblank(crtc);
return true;
}
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 6/7] drm/i915: Remove intel_flip_work infrastructure
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
` (4 preceding siblings ...)
2017-07-20 17:57 ` [PATCH 5/7] drm/i915: adjust has_pending_fb_unpin to atomic Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-07-20 17:57 ` [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit Daniel Vetter
2017-07-20 18:14 ` ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2 Patchwork
7 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Daniel Vetter
This gets rid of all the interactions between the legacy flip code and
the modeset code. Yay!
This highlights an ommission in the atomic paths, where we fail to
apply a boost to the pending rendering when we miss the target vblank.
But the existing code is still dead and can be removed.
v2: Note that the boosting doesn't work in atomic (Chris).
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 70 ---------------------
drivers/gpu/drm/i915/i915_drv.c | 1 -
drivers/gpu/drm/i915/i915_drv.h | 4 --
drivers/gpu/drm/i915/i915_gem.c | 2 -
drivers/gpu/drm/i915/intel_display.c | 117 +----------------------------------
drivers/gpu/drm/i915/intel_drv.h | 21 +------
drivers/gpu/drm/i915/intel_sprite.c | 8 +--
7 files changed, 3 insertions(+), 220 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 2ef75c1a6119..c25f42c60d61 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -543,75 +543,6 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data)
return 0;
}
-static int i915_gem_pageflip_info(struct seq_file *m, void *data)
-{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc;
- int ret;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
-
- for_each_intel_crtc(dev, crtc) {
- const char pipe = pipe_name(crtc->pipe);
- const char plane = plane_name(crtc->plane);
- struct intel_flip_work *work;
-
- spin_lock_irq(&dev->event_lock);
- work = crtc->flip_work;
- if (work == NULL) {
- seq_printf(m, "No flip due on pipe %c (plane %c)\n",
- pipe, plane);
- } else {
- u32 pending;
- u32 addr;
-
- pending = atomic_read(&work->pending);
- if (pending) {
- seq_printf(m, "Flip ioctl preparing on pipe %c (plane %c)\n",
- pipe, plane);
- } else {
- seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n",
- pipe, plane);
- }
- if (work->flip_queued_req) {
- struct intel_engine_cs *engine = work->flip_queued_req->engine;
-
- seq_printf(m, "Flip queued on %s at seqno %x, last submitted seqno %x [current breadcrumb %x], completed? %d\n",
- engine->name,
- work->flip_queued_req->global_seqno,
- intel_engine_last_submit(engine),
- intel_engine_get_seqno(engine),
- i915_gem_request_completed(work->flip_queued_req));
- } else
- seq_printf(m, "Flip not associated with any ring\n");
- seq_printf(m, "Flip queued on frame %d, (was ready on frame %d), now %d\n",
- work->flip_queued_vblank,
- work->flip_ready_vblank,
- intel_crtc_get_vblank_counter(crtc));
- seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
-
- if (INTEL_GEN(dev_priv) >= 4)
- addr = I915_HI_DISPBASE(I915_READ(DSPSURF(crtc->plane)));
- else
- addr = I915_READ(DSPADDR(crtc->plane));
- seq_printf(m, "Current scanout address 0x%08x\n", addr);
-
- if (work->pending_flip_obj) {
- seq_printf(m, "New framebuffer address 0x%08lx\n", (long)work->gtt_offset);
- seq_printf(m, "MMIO update completed? %d\n", addr == work->gtt_offset);
- }
- }
- spin_unlock_irq(&dev->event_lock);
- }
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -4854,7 +4785,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_gem_gtt", i915_gem_gtt_info, 0},
{"i915_gem_pin_display", i915_gem_gtt_info, 0, (void *)1},
{"i915_gem_stolen", i915_gem_stolen_list_info },
- {"i915_gem_pageflip", i915_gem_pageflip_info, 0},
{"i915_gem_request", i915_gem_request_info, 0},
{"i915_gem_seqno", i915_gem_seqno_info, 0},
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index d36ffcdbb89a..6b583dc2eb1f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -876,7 +876,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
spin_lock_init(&dev_priv->uncore.lock);
spin_lock_init(&dev_priv->mm.object_stat_lock);
- spin_lock_init(&dev_priv->mmio_flip_lock);
mutex_init(&dev_priv->sb_lock);
mutex_init(&dev_priv->modeset_restore_lock);
mutex_init(&dev_priv->av_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9b055deca36d..aaa8ed5935ae 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2146,9 +2146,6 @@ struct drm_i915_private {
/* protects the irq masks */
spinlock_t irq_lock;
- /* protects the mmio flip data */
- spinlock_t mmio_flip_lock;
-
bool display_irqs_enabled;
/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
@@ -2253,7 +2250,6 @@ struct drm_i915_private {
struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
struct intel_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
- wait_queue_head_t pending_flip_queue;
#ifdef CONFIG_DEBUG_FS
struct intel_pipe_crc pipe_crc[I915_MAX_PIPES];
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d6f9b4cb6e9b..1a8842f143fc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4936,8 +4936,6 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
init_waitqueue_head(&dev_priv->gpu_error.wait_queue);
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
- init_waitqueue_head(&dev_priv->pending_flip_queue);
-
atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0);
spin_lock_init(&dev_priv->fb_tracking.lock);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bd0488a72503..c10966ebf6fc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -49,11 +49,6 @@
#include <linux/dma_remapping.h>
#include <linux/reservation.h>
-static bool is_mmio_work(struct intel_flip_work *work)
-{
- return work->mmio_work.func;
-}
-
/* Primary plane formats for gen <= 3 */
static const uint32_t i8xx_primary_formats[] = {
DRM_FORMAT_C8,
@@ -3566,35 +3561,6 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
}
-static bool abort_flip_on_reset(struct intel_crtc *crtc)
-{
- struct i915_gpu_error *error = &to_i915(crtc->base.dev)->gpu_error;
-
- if (i915_reset_backoff(error))
- return true;
-
- if (crtc->reset_count != i915_reset_count(error))
- return true;
-
- return false;
-}
-
-static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- bool pending;
-
- if (abort_flip_on_reset(intel_crtc))
- return false;
-
- spin_lock_irq(&dev->event_lock);
- pending = to_intel_crtc(crtc)->flip_work != NULL;
- spin_unlock_irq(&dev->event_lock);
-
- return pending;
-}
-
static void intel_update_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *old_crtc_state)
{
@@ -4172,57 +4138,6 @@ bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv)
return false;
}
-static void page_flip_completed(struct intel_crtc *intel_crtc)
-{
- struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
- struct intel_flip_work *work = intel_crtc->flip_work;
-
- intel_crtc->flip_work = NULL;
-
- if (work->event)
- drm_crtc_send_vblank_event(&intel_crtc->base, work->event);
-
- drm_crtc_vblank_put(&intel_crtc->base);
-
- wake_up_all(&dev_priv->pending_flip_queue);
- trace_i915_flip_complete(intel_crtc->plane,
- work->pending_flip_obj);
-
- queue_work(dev_priv->wq, &work->unpin_work);
-}
-
-static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- long ret;
-
- WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
-
- ret = wait_event_interruptible_timeout(
- dev_priv->pending_flip_queue,
- !intel_crtc_has_pending_flip(crtc),
- 60*HZ);
-
- if (ret < 0)
- return ret;
-
- if (ret == 0) {
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_flip_work *work;
-
- spin_lock_irq(&dev->event_lock);
- work = intel_crtc->flip_work;
- if (work && !is_mmio_work(work)) {
- WARN_ONCE(1, "Removing stuck page flip\n");
- page_flip_completed(intel_crtc);
- }
- spin_unlock_irq(&dev->event_lock);
- }
-
- return 0;
-}
-
void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
{
u32 temp;
@@ -5829,8 +5744,6 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
return;
if (crtc->primary->state->visible) {
- WARN_ON(intel_crtc->flip_work);
-
intel_pre_disable_primary_noatomic(crtc);
intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
@@ -10103,35 +10016,11 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
static void intel_crtc_destroy(struct drm_crtc *crtc)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct intel_flip_work *work;
-
- spin_lock_irq(&dev->event_lock);
- work = intel_crtc->flip_work;
- intel_crtc->flip_work = NULL;
- spin_unlock_irq(&dev->event_lock);
-
- if (work) {
- cancel_work_sync(&work->mmio_work);
- cancel_work_sync(&work->unpin_work);
- kfree(work);
- }
drm_crtc_cleanup(crtc);
-
kfree(intel_crtc);
}
-static inline void intel_mark_page_flip_active(struct intel_crtc *crtc,
- struct intel_flip_work *work)
-{
- work->flip_queued_vblank = intel_crtc_get_vblank_counter(crtc);
-
- /* Ensure that the work item is consistent when activating it ... */
- smp_mb__before_atomic();
- atomic_set(&work->pending, 1);
-}
-
/**
* intel_wm_need_update - Check whether watermarks need updating
* @plane: drm plane
@@ -11950,10 +11839,6 @@ static int intel_atomic_prepare_commit(struct drm_device *dev,
if (state->legacy_cursor_update)
continue;
- ret = intel_crtc_wait_for_pending_flips(crtc);
- if (ret)
- return ret;
-
if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
flush_workqueue(dev_priv->wq);
}
@@ -12757,7 +12642,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- intel_pipe_update_end(intel_crtc, NULL);
+ intel_pipe_update_end(intel_crtc);
}
/**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 04f80b013db9..9cb7e781e863 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -797,7 +797,6 @@ struct intel_crtc {
u8 plane_ids_mask;
unsigned long long enabled_power_domains;
struct intel_overlay *overlay;
- struct intel_flip_work *flip_work;
atomic_t unpin_work_count;
@@ -1132,24 +1131,6 @@ intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum plane plane)
return dev_priv->plane_to_crtc_mapping[plane];
}
-struct intel_flip_work {
- struct work_struct unpin_work;
- struct work_struct mmio_work;
-
- struct drm_crtc *crtc;
- struct i915_vma *old_vma;
- struct drm_framebuffer *old_fb;
- struct drm_i915_gem_object *pending_flip_obj;
- struct drm_pending_vblank_event *event;
- atomic_t pending;
- u32 flip_count;
- u32 gtt_offset;
- struct drm_i915_gem_request *flip_queued_req;
- u32 flip_queued_vblank;
- u32 flip_ready_vblank;
- unsigned int rotation;
-};
-
struct intel_load_detect_pipe {
struct drm_atomic_state *restore_state;
};
@@ -1903,7 +1884,7 @@ struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
void intel_pipe_update_start(struct intel_crtc *crtc);
-void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work);
+void intel_pipe_update_end(struct intel_crtc *crtc);
/* intel_tv.c */
void intel_tv_init(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 94f9a1332dbf..8e25694a1508 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -176,7 +176,7 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
* re-enables interrupts and verifies the update was actually completed
* before a vblank using the value of @start_vbl_count.
*/
-void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work)
+void intel_pipe_update_end(struct intel_crtc *crtc)
{
enum pipe pipe = crtc->pipe;
int scanline_end = intel_get_crtc_scanline(crtc);
@@ -184,12 +184,6 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work
ktime_t end_vbl_time = ktime_get();
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- if (work) {
- work->flip_queued_vblank = end_vbl_count;
- smp_mb__before_atomic();
- atomic_set(&work->pending, 1);
- }
-
trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
/* We're still in the vblank-evade critical section, this can't race.
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
` (5 preceding siblings ...)
2017-07-20 17:57 ` [PATCH 6/7] drm/i915: Remove intel_flip_work infrastructure Daniel Vetter
@ 2017-07-20 17:57 ` Daniel Vetter
2017-07-20 20:47 ` Daniel Vetter
2017-07-20 18:14 ` ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2 Patchwork
7 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 17:57 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter
The core already does this in setup_commit(). With this we can also
remove the unpin_work_count since it's the last user, and also remove
the loop since that was only used for stalling against legacy flips.
v2: Amend commit message a bit (Chris).
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/i915/intel_display.c | 13 +------------
drivers/gpu/drm/i915/intel_drv.h | 2 --
2 files changed, 1 insertion(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c10966ebf6fc..1009ad9d8221 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11830,18 +11830,7 @@ static int intel_atomic_check(struct drm_device *dev,
static int intel_atomic_prepare_commit(struct drm_device *dev,
struct drm_atomic_state *state)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_crtc_state *crtc_state;
- struct drm_crtc *crtc;
- int i, ret;
-
- for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
- if (state->legacy_cursor_update)
- continue;
-
- if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
- flush_workqueue(dev_priv->wq);
- }
+ int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9cb7e781e863..96402c06e295 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -798,8 +798,6 @@ struct intel_crtc {
unsigned long long enabled_power_domains;
struct intel_overlay *overlay;
- atomic_t unpin_work_count;
-
/* Display surface base address adjustement for pageflips. Note that on
* gen4+ this only adjusts up to a tile, offsets within a tile are
* handled in the hw itself (with the TILEOFF register). */
--
2.13.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 21+ messages in thread
* ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
` (6 preceding siblings ...)
2017-07-20 17:57 ` [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit Daniel Vetter
@ 2017-07-20 18:14 ` Patchwork
2017-07-20 19:45 ` Chris Wilson
7 siblings, 1 reply; 21+ messages in thread
From: Patchwork @ 2017-07-20 18:14 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx
== Series Details ==
Series: gpu reset and page_flip removal, take 2
URL : https://patchwork.freedesktop.org/series/27664/
State : success
== Summary ==
Series 27664v1 gpu reset and page_flip removal, take 2
https://patchwork.freedesktop.org/api/1.0/series/27664/revisions/1/mbox/
Test kms_force_connector_basic:
Subgroup prune-stale-modes:
pass -> SKIP (fi-ivb-3520m) fdo#101048
Test kms_pipe_crc_basic:
Subgroup suspend-read-crc-pipe-b:
dmesg-warn -> PASS (fi-byt-n2820) fdo#101705
fdo#101048 https://bugs.freedesktop.org/show_bug.cgi?id=101048
fdo#101705 https://bugs.freedesktop.org/show_bug.cgi?id=101705
fi-bdw-5557u total:279 pass:268 dwarn:0 dfail:0 fail:0 skip:11 time:447s
fi-bdw-gvtdvm total:279 pass:265 dwarn:0 dfail:0 fail:0 skip:14 time:427s
fi-blb-e6850 total:279 pass:224 dwarn:1 dfail:0 fail:0 skip:54 time:353s
fi-bsw-n3050 total:279 pass:243 dwarn:0 dfail:0 fail:0 skip:36 time:532s
fi-bxt-j4205 total:279 pass:260 dwarn:0 dfail:0 fail:0 skip:19 time:511s
fi-byt-j1900 total:279 pass:255 dwarn:0 dfail:0 fail:0 skip:24 time:490s
fi-byt-n2820 total:279 pass:251 dwarn:0 dfail:0 fail:0 skip:28 time:482s
fi-glk-2a total:279 pass:260 dwarn:0 dfail:0 fail:0 skip:19 time:605s
fi-hsw-4770 total:279 pass:263 dwarn:0 dfail:0 fail:0 skip:16 time:440s
fi-hsw-4770r total:279 pass:263 dwarn:0 dfail:0 fail:0 skip:16 time:413s
fi-ilk-650 total:279 pass:229 dwarn:0 dfail:0 fail:0 skip:50 time:414s
fi-ivb-3520m total:279 pass:260 dwarn:0 dfail:0 fail:0 skip:19 time:504s
fi-ivb-3770 total:279 pass:261 dwarn:0 dfail:0 fail:0 skip:18 time:481s
fi-kbl-7500u total:279 pass:261 dwarn:0 dfail:0 fail:0 skip:18 time:470s
fi-kbl-7560u total:279 pass:269 dwarn:0 dfail:0 fail:0 skip:10 time:571s
fi-kbl-r total:279 pass:261 dwarn:0 dfail:0 fail:0 skip:18 time:588s
fi-pnv-d510 total:279 pass:222 dwarn:2 dfail:0 fail:0 skip:55 time:567s
fi-skl-6260u total:279 pass:269 dwarn:0 dfail:0 fail:0 skip:10 time:472s
fi-skl-6700hq total:279 pass:262 dwarn:0 dfail:0 fail:0 skip:17 time:582s
fi-skl-6700k total:279 pass:261 dwarn:0 dfail:0 fail:0 skip:18 time:471s
fi-skl-6770hq total:279 pass:269 dwarn:0 dfail:0 fail:0 skip:10 time:481s
fi-skl-gvtdvm total:279 pass:266 dwarn:0 dfail:0 fail:0 skip:13 time:438s
fi-snb-2520m total:279 pass:251 dwarn:0 dfail:0 fail:0 skip:28 time:548s
fi-snb-2600 total:279 pass:250 dwarn:0 dfail:0 fail:0 skip:29 time:403s
7e935d2dd0d2f5fc21fd0fe9cd2450b338f348fb drm-tip: 2017y-07m-20d-17h-14m-10s UTC integration manifest
db0ec16 drm/i915: More surgically unbreak the modeset vs reset deadlock
93e458a drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
cfe7b42 drm/i915: Avoid the gpu reset vs. modeset deadlock
== Logs ==
For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5254/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2
2017-07-20 18:14 ` ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2 Patchwork
@ 2017-07-20 19:45 ` Chris Wilson
0 siblings, 0 replies; 21+ messages in thread
From: Chris Wilson @ 2017-07-20 19:45 UTC (permalink / raw)
To: Patchwork, Daniel Vetter; +Cc: intel-gfx
Quoting Patchwork (2017-07-20 19:14:57)
> == Series Details ==
>
> Series: gpu reset and page_flip removal, take 2
> URL : https://patchwork.freedesktop.org/series/27664/
> State : success
>
> == Summary ==
>
> Series 27664v1 gpu reset and page_flip removal, take 2
> https://patchwork.freedesktop.org/api/1.0/series/27664/revisions/1/mbox/
>
> Test kms_force_connector_basic:
> Subgroup prune-stale-modes:
> pass -> SKIP (fi-ivb-3520m) fdo#101048
> Test kms_pipe_crc_basic:
> Subgroup suspend-read-crc-pipe-b:
> dmesg-warn -> PASS (fi-byt-n2820) fdo#101705
>
> fdo#101048 https://bugs.freedesktop.org/show_bug.cgi?id=101048
> fdo#101705 https://bugs.freedesktop.org/show_bug.cgi?id=101705
>
> fi-bdw-5557u total:279 pass:268 dwarn:0 dfail:0 fail:0 skip:11 time:447s
> fi-bdw-gvtdvm total:279 pass:265 dwarn:0 dfail:0 fail:0 skip:14 time:427s
> fi-blb-e6850 total:279 pass:224 dwarn:1 dfail:0 fail:0 skip:54 time:353s
Notable for its absence here is the dwarn remains:
[ 174.447751] [IGT] gem_ringfill: executing
[ 174.454092] [drm:vgem_gem_dumb_create [vgem]] Created object of size 1
[ 174.578472] [IGT] gem_ringfill: starting subtest basic-default-hang
[ 178.720764] [drm:missed_breadcrumb [i915]] rcs0 missed breadcrumb at intel_breadcrumbs_hangcheck+0x5c/0x80 [i915], irq posted? yes, current seqno=321692, last=322350
[ 183.729106] [drm] GPU HANG: ecode 3:0:0x657fff41, in gem_ringfill [3184], reason: Hang on rcs0, action: reset
[ 183.729306] [drm:i915_reset_device [i915]] resetting chip
[ 188.897051] i915 0000:00:02.0: i915_reset_device timed out, cancelling all in-flight rendering.
After the reset, so this is the struct_mutex deadlock in the atomic state cleanup.
[ 188.906558] [drm:intel_disable_pipe [i915]] disabling pipe A
[ 188.921697] [drm:i9xx_get_fifo_size [i915]] FIFO size - (0x00001d9c) A: 28
[ 188.921742] [drm:i9xx_get_fifo_size [i915]] FIFO size - (0x00001d9c) B: 31
[ 188.921785] [drm:i9xx_update_wm [i915]] FIFO watermarks - A: 26, B: 29
[ 188.921823] [drm:i9xx_update_wm [i915]] Setting FIFO watermarks - A: 26, B: 29, C: 2, SR 1
[ 188.921861] [drm:intel_atomic_commit_tail [i915]] [ENCODER:33:CRT]
[ 188.921898] [drm:verify_connector_state.isra.72 [i915]] [CONNECTOR:32:VGA-1]
[ 188.921948] [drm:intel_atomic_commit_tail [i915]] [CRTC:28:pipe A]
[ 188.921982] [drm:intel_power_well_disable [i915]] disabling always-on
[ 188.922045] drm/i915: Resetting chip after gpu hang
[ 188.922098] [drm:i915_gem_reset_prepare_engine [i915]] rcs0 pardoned
[ 189.423823] [drm:gen3_stop_rings [i915]] rcs0: timed out on STOP_RING
[ 189.452169] [drm:init_workarounds_ring [i915]] rcs0: Number of context specific w/a: 0
[ 189.452252] [drm:intel_hpll_vco [i915]] HPLL VCO 4000000 kHz
[ 189.452289] [drm:intel_update_cdclk [i915]] Current CD clock rate: 333333 kHz, VCO: 4000000 kHz, ref: 0 kHz
[ 189.452325] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.452355] [drm:intel_power_well_disable [i915]] disabling always-on
[ 189.452390] [drm:intel_set_plane_visible [i915]] pipe A active planes 0x0
[ 189.452425] [drm:intel_modeset_setup_hw_state [i915]] [CRTC:28:pipe A] hw state readout: disabled
[ 189.452455] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.452485] [drm:intel_power_well_disable [i915]] disabling always-on
[ 189.452520] [drm:intel_set_plane_visible [i915]] pipe B active planes 0x0
[ 189.452554] [drm:intel_modeset_setup_hw_state [i915]] [CRTC:31:pipe B] hw state readout: disabled
[ 189.452584] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.453020] [drm:intel_power_well_disable [i915]] disabling always-on
[ 189.453056] [drm:intel_modeset_setup_hw_state [i915]] [ENCODER:33:CRT] hw state readout: disabled, pipe A
[ 189.453089] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.453119] [drm:intel_power_well_disable [i915]] disabling always-on
[ 189.453154] [drm:intel_modeset_setup_hw_state [i915]] [CONNECTOR:32:VGA-1] hw state readout: disabled
[ 189.453192] [drm:intel_dump_pipe_config [i915]] [CRTC:28:pipe A][setup_hw_state]
[ 189.453226] [drm:intel_dump_pipe_config [i915]] cpu_transcoder: A, pipe bpp: 0, dithering: 0
[ 189.453260] [drm:intel_dump_pipe_config [i915]] audio: 0, infoframes: 0
[ 189.453293] [drm:intel_dump_pipe_config [i915]] requested mode:
[ 189.453301] [drm:drm_mode_debug_printmodeline] Modeline 0:"" 0 0 0 0 0 0 0 0 0 0 0x0 0x0
[ 189.453334] [drm:intel_dump_pipe_config [i915]] adjusted mode:
[ 189.453339] [drm:drm_mode_debug_printmodeline] Modeline 0:"" 0 0 0 0 0 0 0 0 0 0 0x0 0x0
[ 189.453373] [drm:intel_dump_pipe_config [i915]] crtc timings: 0 0 0 0 0 0 0 0 0, type: 0x0 flags: 0x0
[ 189.453407] [drm:intel_dump_pipe_config [i915]] port clock: 0, pipe src size: 0x0, pixel rate 0
[ 189.453441] [drm:intel_dump_pipe_config [i915]] gmch pfit: control: 0x00000000, ratios: 0x00000000, lvds border: 0x00000000
[ 189.453474] [drm:intel_dump_pipe_config [i915]] ips: 0, double wide: 0
[ 189.453508] [drm:intel_dpll_dump_hw_state [i915]] dpll_hw_state: dpll: 0x0, dpll_md: 0x0, fp0: 0x0, fp1: 0x0
[ 189.453542] [drm:intel_dump_pipe_config [i915]] planes on this crtc
[ 189.453575] [drm:intel_dump_pipe_config [i915]] [PLANE:26:plane A] disabled, scaler_id = 0
[ 189.453609] [drm:intel_dump_pipe_config [i915]] [PLANE:27:cursor A] disabled, scaler_id = 0
[ 189.454327] [drm:intel_dump_pipe_config [i915]] [CRTC:31:pipe B][setup_hw_state]
[ 189.454361] [drm:intel_dump_pipe_config [i915]] cpu_transcoder: B, pipe bpp: 0, dithering: 0
[ 189.454395] [drm:intel_dump_pipe_config [i915]] audio: 0, infoframes: 0
[ 189.454428] [drm:intel_dump_pipe_config [i915]] requested mode:
[ 189.454433] [drm:drm_mode_debug_printmodeline] Modeline 0:"" 0 0 0 0 0 0 0 0 0 0 0x0 0x0
[ 189.454467] [drm:intel_dump_pipe_config [i915]] adjusted mode:
[ 189.454471] [drm:drm_mode_debug_printmodeline] Modeline 0:"" 0 0 0 0 0 0 0 0 0 0 0x0 0x0
[ 189.454505] [drm:intel_dump_pipe_config [i915]] crtc timings: 0 0 0 0 0 0 0 0 0, type: 0x0 flags: 0x0
[ 189.454539] [drm:intel_dump_pipe_config [i915]] port clock: 0, pipe src size: 0x0, pixel rate 0
[ 189.454573] [drm:intel_dump_pipe_config [i915]] gmch pfit: control: 0x00000000, ratios: 0x00000000, lvds border: 0x00000000
[ 189.454606] [drm:intel_dump_pipe_config [i915]] ips: 0, double wide: 0
[ 189.455122] [drm:intel_dpll_dump_hw_state [i915]] dpll_hw_state: dpll: 0x0, dpll_md: 0x0, fp0: 0x0, fp1: 0x0
[ 189.455156] [drm:intel_dump_pipe_config [i915]] planes on this crtc
[ 189.455190] [drm:intel_dump_pipe_config [i915]] [PLANE:29:plane B] disabled, scaler_id = 0
[ 189.455224] [drm:intel_dump_pipe_config [i915]] [PLANE:30:cursor B] disabled, scaler_id = 0
[ 189.455258] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.455293] [drm:i915_redisable_vga_power_on [i915]] Something enabled VGA plane, disabling it
[ 189.455935] [drm:intel_power_well_disable [i915]] disabling always-on
[ 189.455987] [drm:intel_atomic_check [i915]] [CONNECTOR:32:VGA-1] checking for sink bpp constrains
[ 189.456022] [drm:intel_atomic_check [i915]] hw max bpp: 24, pipe bpp: 24, dithering: 0
[ 189.456056] [drm:intel_dump_pipe_config [i915]] [CRTC:28:pipe A][modeset]
[ 189.456090] [drm:intel_dump_pipe_config [i915]] cpu_transcoder: A, pipe bpp: 24, dithering: 0
[ 189.456123] [drm:intel_dump_pipe_config [i915]] audio: 0, infoframes: 0
[ 189.456157] [drm:intel_dump_pipe_config [i915]] requested mode:
[ 189.456162] [drm:drm_mode_debug_printmodeline] Modeline 0:"1920x1080" 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[ 189.456195] [drm:intel_dump_pipe_config [i915]] adjusted mode:
[ 189.456200] [drm:drm_mode_debug_printmodeline] Modeline 0:"1920x1080" 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[ 189.456235] [drm:intel_dump_pipe_config [i915]] crtc timings: 148500 1920 2008 2052 2200 1080 1084 1089 1125, type: 0x48 flags: 0x5
[ 189.456268] [drm:intel_dump_pipe_config [i915]] port clock: 148500, pipe src size: 1920x1080, pixel rate 148500
[ 189.456302] [drm:intel_dump_pipe_config [i915]] gmch pfit: control: 0x00000000, ratios: 0x00000000, lvds border: 0x00000000
[ 189.456336] [drm:intel_dump_pipe_config [i915]] ips: 0, double wide: 0
[ 189.456370] [drm:intel_dpll_dump_hw_state [i915]] dpll_hw_state: dpll: 0x94010000, dpll_md: 0x0, fp0: 0x40f06, fp1: 0x40f06
[ 189.456403] [drm:intel_dump_pipe_config [i915]] planes on this crtc
[ 189.456437] [drm:intel_dump_pipe_config [i915]] [PLANE:26:plane A] disabled, scaler_id = 0
[ 189.456470] [drm:intel_dump_pipe_config [i915]] [PLANE:27:cursor A] disabled, scaler_id = 0
[ 189.457271] [drm:intel_power_well_enable [i915]] enabling always-on
[ 189.457311] [drm:intel_atomic_commit_tail [i915]] [ENCODER:33:CRT]
[ 189.458396] [drm:i9xx_get_fifo_size [i915]] FIFO size - (0x00001d9c) A: 28
[ 189.458426] [drm:intel_calculate_wm [i915]] FIFO entries required for mode: 49
[ 189.458454] [drm:intel_calculate_wm [i915]] FIFO watermark level: -21
[ 189.458483] [drm:i9xx_get_fifo_size [i915]] FIFO size - (0x00001d9c) B: 31
[ 189.458511] [drm:i9xx_update_wm [i915]] FIFO watermarks - A: 8, B: 29
[ 189.458541] [drm:i9xx_update_wm [i915]] self-refresh entries: 120
[ 189.458570] [drm:i9xx_update_wm [i915]] Setting FIFO watermarks - A: 8, B: 29, C: 2, SR 1
[ 189.458605] [drm:intel_enable_pipe [i915]] enabling pipe A
[ 189.475968] [drm:verify_connector_state.isra.72 [i915]] [CONNECTOR:32:VGA-1]
[ 189.476026] [drm:intel_atomic_commit_tail [i915]] [CRTC:28:pipe A]
[ 189.476078] [drm:intel_atomic_commit_tail [i915]] [CRTC:31:pipe B]
[ 189.476303] [drm:intel_crt_detect [i915]] [CONNECTOR:32:VGA-1] force=0
[ 189.486870] [IGT] gem_ringfill: exiting, ret=0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock
2017-07-20 17:57 ` [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
@ 2017-07-20 19:47 ` Chris Wilson
2017-07-20 20:04 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2017-07-20 19:47 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter, Daniel Vetter, Mika Kuoppala
Quoting Daniel Vetter (2017-07-20 18:57:48)
> ... using the biggest hammer we have. This is essentially a weaponized
> version of the timeout-based wedging Chris added in
>
> commit 36703e79a982c8ce5a8e43833291f2719e92d0d1
> Author: Chris Wilson <chris@chris-wilson.co.uk>
> Date: Thu Jun 22 11:56:25 2017 +0100
>
> drm/i915: Break modeset deadlocks on reset
>
> Because defense-in-depth is good it's good to still have both. Also
> note that with the locking change we can now restrict this a lot (old
> gpus and special testing only), so this doesn't kill the TDR benefits
> on at least anything remotely modern.
>
> And futuremore with a few tricks it should be possible to make a much
> more educated guess about whether an atomic commit is stuck waiting on
> the gpu (atomic_t counting the pending i915_sw_fence used by the
> atomic modeset code should do it), so we can improve this.
>
> But for now just start with something that is guaranteed to recover
> faster, for much better CI througput.
>
> This defacto reverts TDR on these platforms, but there's not really a
> single commit to specify as the sole offender.
>
> v2: Add a debug message to explain what's going on. We can't DRM_ERROR
> because that spams CI. And the timeout based fallback still prints a
> DRM_ERROR, in case something goes wrong.
>
> Fixes: 4680816be336 ("drm/i915: Wait first for submission, before waiting for request completion")
> Fixes: 221fe7994554 ("drm/i915: Perform a direct reset of the GPU from the waiter")
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
> drivers/gpu/drm/i915/intel_display.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 02b1f4966049..995522e40ec1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3471,6 +3471,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
> !gpu_reset_clobbers_display(dev_priv))
> return;
>
> + /* We have a modeset vs reset deadlock, defensively unbreak it.
> + *
> + * FIXME: We can do a _lot_ better, this is just a first iteration.*/
> + i915_gem_set_wedged(dev_priv);
> + DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
I meant this a dev_err(). It has user visible impact and user data loss.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock
2017-07-20 19:47 ` Chris Wilson
@ 2017-07-20 20:04 ` Daniel Vetter
2017-07-20 20:16 ` Chris Wilson
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 20:04 UTC (permalink / raw)
To: Chris Wilson; +Cc: Daniel Vetter, Intel Graphics Development, Mika Kuoppala
On Thu, Jul 20, 2017 at 9:47 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 02b1f4966049..995522e40ec1 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -3471,6 +3471,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
>> !gpu_reset_clobbers_display(dev_priv))
>> return;
>>
>> + /* We have a modeset vs reset deadlock, defensively unbreak it.
>> + *
>> + * FIXME: We can do a _lot_ better, this is just a first iteration.*/
>> + i915_gem_set_wedged(dev_priv);
>> + DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
>
> I meant this a dev_err(). It has user visible impact and user data loss.
stop_rings is gone so I can't differentiate, and DRM_ERROR breaks CI.
Which after your timeout is the only point of this patch really. I
guess I could throw a pr_notice or so in there, but we already do
that. This was all removed in
commit 7b4d3a16dd97be0ebc793ea046b9af9d5c9b1b1a
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date: Mon Jul 4 08:08:37 2016 +0100
drm/i915: Remove stop-rings debugfs interface
Should I explain this better in the commit message? I tried already ...
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - 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] 21+ messages in thread
* Re: [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock
2017-07-20 20:04 ` Daniel Vetter
@ 2017-07-20 20:16 ` Chris Wilson
2017-07-20 20:18 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Chris Wilson @ 2017-07-20 20:16 UTC (permalink / raw)
To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development, Mika Kuoppala
Quoting Daniel Vetter (2017-07-20 21:04:50)
> On Thu, Jul 20, 2017 at 9:47 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> index 02b1f4966049..995522e40ec1 100644
> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> @@ -3471,6 +3471,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
> >> !gpu_reset_clobbers_display(dev_priv))
> >> return;
> >>
> >> + /* We have a modeset vs reset deadlock, defensively unbreak it.
> >> + *
> >> + * FIXME: We can do a _lot_ better, this is just a first iteration.*/
> >> + i915_gem_set_wedged(dev_priv);
> >> + DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
> >
> > I meant this a dev_err(). It has user visible impact and user data loss.
>
> stop_rings is gone so I can't differentiate, and DRM_ERROR breaks CI.
> Which after your timeout is the only point of this patch really.
So drop this patch. If the only reason is to sweep the bug under the
carpet, don't. I thought this patch was to move the wedge to where you
planned to replace it with the refined approach to abort the modeset.
> guess I could throw a pr_notice or so in there, but we already do
> that. This was all removed in
>
> commit 7b4d3a16dd97be0ebc793ea046b9af9d5c9b1b1a
> Author: Chris Wilson <chris@chris-wilson.co.uk>
> Date: Mon Jul 4 08:08:37 2016 +0100
>
> drm/i915: Remove stop-rings debugfs interface
>
> Should I explain this better in the commit message? I tried already ...
No idea what you mean. If you mean you want to know whether this error
was simulated or not, look in the error state. But the point of this
series is to avoid the dev_err() in the first place, in which case why
do we care whether it was simulated or not, if we hit the err it is a
bug and CI should be flagging it.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock
2017-07-20 20:16 ` Chris Wilson
@ 2017-07-20 20:18 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 20:18 UTC (permalink / raw)
To: Chris Wilson; +Cc: Daniel Vetter, Intel Graphics Development, Mika Kuoppala
On Thu, Jul 20, 2017 at 10:16 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> Quoting Daniel Vetter (2017-07-20 21:04:50)
>> On Thu, Jul 20, 2017 at 9:47 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> >> index 02b1f4966049..995522e40ec1 100644
>> >> --- a/drivers/gpu/drm/i915/intel_display.c
>> >> +++ b/drivers/gpu/drm/i915/intel_display.c
>> >> @@ -3471,6 +3471,12 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
>> >> !gpu_reset_clobbers_display(dev_priv))
>> >> return;
>> >>
>> >> + /* We have a modeset vs reset deadlock, defensively unbreak it.
>> >> + *
>> >> + * FIXME: We can do a _lot_ better, this is just a first iteration.*/
>> >> + i915_gem_set_wedged(dev_priv);
>> >> + DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
>> >
>> > I meant this a dev_err(). It has user visible impact and user data loss.
>>
>> stop_rings is gone so I can't differentiate, and DRM_ERROR breaks CI.
>> Which after your timeout is the only point of this patch really.
>
> So drop this patch. If the only reason is to sweep the bug under the
> carpet, don't. I thought this patch was to move the wedge to where you
> planned to replace it with the refined approach to abort the modeset.
It fixes a regression we have in CI, because the dmesg-warn can hide
other stuff. If you want, resurrect some better way to handle that,
meanwhile this here gets the job done. Since the latter patches don't
work I'm proposing just this one here for merging.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - 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] 21+ messages in thread
* Re: [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit
2017-07-20 17:57 ` [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit Daniel Vetter
@ 2017-07-20 20:47 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-20 20:47 UTC (permalink / raw)
To: Intel Graphics Development; +Cc: Daniel Vetter
On Thu, Jul 20, 2017 at 07:57:54PM +0200, Daniel Vetter wrote:
> The core already does this in setup_commit(). With this we can also
> remove the unpin_work_count since it's the last user, and also remove
> the loop since that was only used for stalling against legacy flips.
>
> v2: Amend commit message a bit (Chris).
>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Ok, I pulled in 4-7 of this series. I'll drop 2&3 since they're not a
complete solution.
-Daniel
> ---
> drivers/gpu/drm/i915/intel_display.c | 13 +------------
> drivers/gpu/drm/i915/intel_drv.h | 2 --
> 2 files changed, 1 insertion(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c10966ebf6fc..1009ad9d8221 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11830,18 +11830,7 @@ static int intel_atomic_check(struct drm_device *dev,
> static int intel_atomic_prepare_commit(struct drm_device *dev,
> struct drm_atomic_state *state)
> {
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - struct drm_crtc_state *crtc_state;
> - struct drm_crtc *crtc;
> - int i, ret;
> -
> - for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> - if (state->legacy_cursor_update)
> - continue;
> -
> - if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
> - flush_workqueue(dev_priv->wq);
> - }
> + int ret;
>
> ret = mutex_lock_interruptible(&dev->struct_mutex);
> if (ret)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 9cb7e781e863..96402c06e295 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -798,8 +798,6 @@ struct intel_crtc {
> unsigned long long enabled_power_domains;
> struct intel_overlay *overlay;
>
> - atomic_t unpin_work_count;
> -
> /* Display surface base address adjustement for pageflips. Note that on
> * gen4+ this only adjusts up to a tile, offsets within a tile are
> * handled in the hw itself (with the TILEOFF register). */
> --
> 2.13.2
>
--
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] 21+ messages in thread
* Re: [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock
2017-07-20 17:57 ` [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock Daniel Vetter
@ 2017-08-03 19:35 ` Michel Thierry
2017-08-07 15:39 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Michel Thierry @ 2017-08-03 19:35 UTC (permalink / raw)
To: Daniel Vetter, Intel Graphics Development; +Cc: Vetter, Daniel, Kuoppala, Mika
Hi,
First sorry about the delay...
On 7/20/2017 10:57 AM, Daniel Vetter wrote:
> There's no reason to entirely wedge the gpu, for the minimal deadlock
> bugfix we only need to unbreak/decouple the atomic commit from the gpu
> reset. The simplest way to fix that is by replacing the
> unconditional fence wait a the top of commit_tail by a wait which
> completes either when the fences are done (normal case, or when a
> reset doesn't need to touch the display state). Or when the gpu reset
> needs to force-unblock all pending modeset states.
>
> The lesser source of deadlocks is when we try to pin a new framebuffer
> and run into a stall. There's a bunch of places this can happen, like
> eviction, changing the caching mode, acquiring a fence on older
> platforms. And we can't just break the depency loop and keep going,
> the only way would be to break out and restart. But the problem with
> that approach is that we must stall for the reset to complete before
> we grab any locks, and with the atomic infrastructure that's a bit
> tricky. The only place is the ioctl code, and we don't want to insert
> code into e.g. the BUSY ioctl. Hence for that problem just create a
> critical section, and if any code is in there, wedge the GPU. For the
> steady-state this should never be a problem.
>
> Note that in both cases TDR itself keeps working, so from a userspace
> pov this trickery isn't observable. Users themselvs might spot a short
> glitch while the rendering is catching up again, but that's still
> better than pre-TDR where we've thrown away all the rendering,
> including innocent batches. Also, this fixes the regression TDR
> introduced of making gpu resets deadlock-prone when we do need to
> touch the display.
>
> One thing I noticed is that gpu_error.flags seems to use both our own
> wait-queue in gpu_error.wait_queue, and the generic wait_on_bit
> facilities. Not entirely sure why this inconsistency exists, I just
> picked one style.
>
> A possible future avenue could be to insert the gpu reset in-between
> ongoing modeset changes, which would avoid the momentary glitch. But
> that's a lot more work to implement in the atomic commit machinery,
> and given that we only need this for pre-g4x hw, of questionable
> utility just for the sake of polishing gpu reset even more on those
> old boxes. It might be useful for other features though.
>
> v2: Rebase onto 4.13 with a s/wait_queue_t/struct wait_queue_entry/.
>
> v3: Really emabarrassing fixup, I checked the wrong bit and broke the
> unbreak/wakeup logic.
>
> v4: Also handle deadlocks in pin_to_display.
>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 3 +++
> drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++++++++++++++++-----
> 2 files changed, 42 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 07e98b07c5bc..9b055deca36d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1505,6 +1505,8 @@ struct i915_gpu_error {
> /* Protected by the above dev->gpu_error.lock. */
> struct i915_gpu_state *first_error;
>
> + atomic_t pending_fb_pin;
> +
> unsigned long missed_irq_rings;
>
> /**
> @@ -1564,6 +1566,7 @@ struct i915_gpu_error {
> unsigned long flags;
> #define I915_RESET_BACKOFF 0
> #define I915_RESET_HANDOFF 1
> +#define I915_RESET_MODESET 2
> #define I915_WEDGED (BITS_PER_LONG - 1)
> #define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES)
>
Since you still need to resend this, could you also update the
I915_RESET_ENGINE overflow check in i915_handle_error? i.e.:
---BUILD_BUG_ON(I915_RESET_HANDOFF >= I915_RESET_ENGINE);
+++BUILD_BUG_ON(I915_RESET_MODESET >= I915_RESET_ENGINE);
Not that we would have this problem anytime soon...
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f6bd6282d7f7..63ea8d6b2ebd 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2162,6 +2162,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
> */
> intel_runtime_pm_get(dev_priv);
>
> + atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
> +
Do we also need this in intel_overlay_do_put_image? It is also being
called when the struct_mutex is held.
> vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
> if (IS_ERR(vma))
> goto err;
> @@ -2189,6 +2191,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
>
> i915_vma_get(vma);
> err:
> + atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
> +
> intel_runtime_pm_put(dev_priv);
> return vma;
> }
> @@ -3471,11 +3475,14 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
> !gpu_reset_clobbers_display(dev_priv))
> return;
>
> - /* We have a modeset vs reset deadlock, defensively unbreak it.
> - *
> - * FIXME: We can do a _lot_ better, this is just a first iteration.*/
> - i915_gem_set_wedged(dev_priv);
> - DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
> + /* We have a modeset vs reset deadlock, defensively unbreak it. */
> + set_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
> + wake_up_all(&dev_priv->gpu_error.wait_queue);
> +
> + if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
> + DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
> + i915_gem_set_wedged(dev_priv);
> + }
>
> /*
> * Need mode_config.mutex so that we don't
> @@ -3570,6 +3577,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
> drm_modeset_drop_locks(ctx);
> drm_modeset_acquire_fini(ctx);
> mutex_unlock(&dev->mode_config.mutex);
> +
> + clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
> }
>
> static bool abort_flip_on_reset(struct intel_crtc *crtc)
^^^ this is the only reason of why we need a rebase.
> @@ -12381,6 +12390,30 @@ static void intel_atomic_helper_free_state_worker(struct work_struct *work)
> intel_atomic_helper_free_state(dev_priv);
> }
>
> +static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
> +{
> + struct wait_queue_entry wait_fence, wait_reset;
> + struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
> +
> + init_wait_entry(&wait_fence, 0);
> + init_wait_entry(&wait_reset, 0);
> + for (;;) {
> + prepare_to_wait(&intel_state->commit_ready.wait,
> + &wait_fence, TASK_UNINTERRUPTIBLE);
> + prepare_to_wait(&dev_priv->gpu_error.wait_queue,
> + &wait_reset, TASK_UNINTERRUPTIBLE);
> +
> +
> + if (i915_sw_fence_done(&intel_state->commit_ready)
> + || test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags))
> + break;
> +
> + schedule();
> + }
> + finish_wait(&intel_state->commit_ready.wait, &wait_fence);
> + finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
> +}
> +
> static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> {
> struct drm_device *dev = state->dev;
> @@ -12394,7 +12427,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> unsigned crtc_vblank_mask = 0;
> int i;
>
> - i915_sw_fence_wait(&intel_state->commit_ready);
> + intel_atomic_commit_fence_wait(intel_state);
>
> drm_atomic_helper_wait_for_dependencies(state);
>
Looks good to me.
-Michel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
2017-07-20 17:57 ` [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit Daniel Vetter
@ 2017-08-03 19:44 ` Michel Thierry
2017-08-07 15:33 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Michel Thierry @ 2017-08-03 19:44 UTC (permalink / raw)
To: Daniel Vetter, Intel Graphics Development; +Cc: Vetter, Daniel, Kuoppala, Mika
On 7/20/2017 10:57 AM, Daniel Vetter wrote:
> Blocking in a worker is ok, that's what the unbound_wq is for. And it
> unifies the paths between the blocking and nonblocking commit, giving
> me just one path where I have to implement the deadlock avoidance
> trickery in the next patch.
>
> I first tried to implement the following patch without this rework, but
> force-completing i915_sw_fence creates some serious challenges around
> properly cleaning things up. So wasn't a feasible short-term approach.
> Another approach would be to simple keep track of all pending atomic
> commit work items and manually queue them from the reset code. With the
> caveat that double-queue in case we race with the i915_sw_fence must be
> avoided. Given all that, taking the cost of a double schedule in atomic
> for the short-term fix is the best approach, but can be changed in the
> future of course.
>
> v2: Amend commit message (Chris).
>
> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
> drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
> 1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 995522e40ec1..f6bd6282d7f7 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12394,6 +12394,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> unsigned crtc_vblank_mask = 0;
> int i;
>
> + i915_sw_fence_wait(&intel_state->commit_ready);
> +
> drm_atomic_helper_wait_for_dependencies(state);
>
> if (intel_state->modeset)
> @@ -12561,10 +12563,7 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
>
> switch (notify) {
> case FENCE_COMPLETE:
> - if (state->base.commit_work.func)
> - queue_work(system_unbound_wq, &state->base.commit_work);
I would add a small comment here, because later-on if someone has doubts
(and use git-blame), it won't be visible that something changed (the
case and break were added by the same commit).
> break;
> -
> case FENCE_FREE:
> {
> struct intel_atomic_helper *helper =
> @@ -12668,14 +12667,14 @@ static int intel_atomic_commit(struct drm_device *dev,
> }
>
> drm_atomic_state_get(state);
> - INIT_WORK(&state->commit_work,
> - nonblock ? intel_atomic_commit_work : NULL);
> + INIT_WORK(&state->commit_work, intel_atomic_commit_work);
>
> i915_sw_fence_commit(&intel_state->commit_ready);
> - if (!nonblock) {
> - i915_sw_fence_wait(&intel_state->commit_ready);
> + if (nonblock)
> + queue_work(system_unbound_wq, &state->commit_work);
> + else
> intel_atomic_commit_tail(state);
> - }
> +
>
> return 0;
> }
Reviewed-by: Michel Thierry <michel.thierry@intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
2017-08-03 19:44 ` Michel Thierry
@ 2017-08-07 15:33 ` Daniel Vetter
2017-08-07 17:06 ` Michel Thierry
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2017-08-07 15:33 UTC (permalink / raw)
To: Michel Thierry
Cc: Vetter, Daniel, Daniel Vetter, Intel Graphics Development,
Kuoppala, Mika
On Thu, Aug 03, 2017 at 12:44:40PM -0700, Michel Thierry wrote:
> On 7/20/2017 10:57 AM, Daniel Vetter wrote:
> > Blocking in a worker is ok, that's what the unbound_wq is for. And it
> > unifies the paths between the blocking and nonblocking commit, giving
> > me just one path where I have to implement the deadlock avoidance
> > trickery in the next patch.
> >
> > I first tried to implement the following patch without this rework, but
> > force-completing i915_sw_fence creates some serious challenges around
> > properly cleaning things up. So wasn't a feasible short-term approach.
> > Another approach would be to simple keep track of all pending atomic
> > commit work items and manually queue them from the reset code. With the
> > caveat that double-queue in case we race with the i915_sw_fence must be
> > avoided. Given all that, taking the cost of a double schedule in atomic
> > for the short-term fix is the best approach, but can be changed in the
> > future of course.
> >
> > v2: Amend commit message (Chris).
> >
> > Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Cc: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> > Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > ---
> > drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
> > 1 file changed, 7 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 995522e40ec1..f6bd6282d7f7 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -12394,6 +12394,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> > unsigned crtc_vblank_mask = 0;
> > int i;
> >
> > + i915_sw_fence_wait(&intel_state->commit_ready);
> > +
> > drm_atomic_helper_wait_for_dependencies(state);
> >
> > if (intel_state->modeset)
> > @@ -12561,10 +12563,7 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
> >
> > switch (notify) {
> > case FENCE_COMPLETE:
> > - if (state->base.commit_work.func)
> > - queue_work(system_unbound_wq, &state->base.commit_work);
>
> I would add a small comment here, because later-on if someone has doubts
> (and use git-blame), it won't be visible that something changed (the case
> and break were added by the same commit).
Hm, not sure what comment I should put here? Suggestions? Only thing I
could come up with was
/* we do blocking waits in the worker, nothing to do here */
But not sure that adds the information you're looking for.
-Daniel
>
> > break;
> > -
> > case FENCE_FREE:
> > {
> > struct intel_atomic_helper *helper =
> > @@ -12668,14 +12667,14 @@ static int intel_atomic_commit(struct drm_device *dev,
> > }
> >
> > drm_atomic_state_get(state);
> > - INIT_WORK(&state->commit_work,
> > - nonblock ? intel_atomic_commit_work : NULL);
> > + INIT_WORK(&state->commit_work, intel_atomic_commit_work);
> >
> > i915_sw_fence_commit(&intel_state->commit_ready);
> > - if (!nonblock) {
> > - i915_sw_fence_wait(&intel_state->commit_ready);
> > + if (nonblock)
> > + queue_work(system_unbound_wq, &state->commit_work);
> > + else
> > intel_atomic_commit_tail(state);
> > - }
> > +
> >
> > return 0;
> > }
>
> Reviewed-by: Michel Thierry <michel.thierry@intel.com>
--
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] 21+ messages in thread
* Re: [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock
2017-08-03 19:35 ` Michel Thierry
@ 2017-08-07 15:39 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-08-07 15:39 UTC (permalink / raw)
To: Michel Thierry
Cc: Vetter, Daniel, Daniel Vetter, Intel Graphics Development,
Kuoppala, Mika
On Thu, Aug 03, 2017 at 12:35:48PM -0700, Michel Thierry wrote:
> Hi,
>
> First sorry about the delay...
>
> On 7/20/2017 10:57 AM, Daniel Vetter wrote:
> > There's no reason to entirely wedge the gpu, for the minimal deadlock
> > bugfix we only need to unbreak/decouple the atomic commit from the gpu
> > reset. The simplest way to fix that is by replacing the
> > unconditional fence wait a the top of commit_tail by a wait which
> > completes either when the fences are done (normal case, or when a
> > reset doesn't need to touch the display state). Or when the gpu reset
> > needs to force-unblock all pending modeset states.
> >
> > The lesser source of deadlocks is when we try to pin a new framebuffer
> > and run into a stall. There's a bunch of places this can happen, like
> > eviction, changing the caching mode, acquiring a fence on older
> > platforms. And we can't just break the depency loop and keep going,
> > the only way would be to break out and restart. But the problem with
> > that approach is that we must stall for the reset to complete before
> > we grab any locks, and with the atomic infrastructure that's a bit
> > tricky. The only place is the ioctl code, and we don't want to insert
> > code into e.g. the BUSY ioctl. Hence for that problem just create a
> > critical section, and if any code is in there, wedge the GPU. For the
> > steady-state this should never be a problem.
> >
> > Note that in both cases TDR itself keeps working, so from a userspace
> > pov this trickery isn't observable. Users themselvs might spot a short
> > glitch while the rendering is catching up again, but that's still
> > better than pre-TDR where we've thrown away all the rendering,
> > including innocent batches. Also, this fixes the regression TDR
> > introduced of making gpu resets deadlock-prone when we do need to
> > touch the display.
> >
> > One thing I noticed is that gpu_error.flags seems to use both our own
> > wait-queue in gpu_error.wait_queue, and the generic wait_on_bit
> > facilities. Not entirely sure why this inconsistency exists, I just
> > picked one style.
> >
> > A possible future avenue could be to insert the gpu reset in-between
> > ongoing modeset changes, which would avoid the momentary glitch. But
> > that's a lot more work to implement in the atomic commit machinery,
> > and given that we only need this for pre-g4x hw, of questionable
> > utility just for the sake of polishing gpu reset even more on those
> > old boxes. It might be useful for other features though.
> >
> > v2: Rebase onto 4.13 with a s/wait_queue_t/struct wait_queue_entry/.
> >
> > v3: Really emabarrassing fixup, I checked the wrong bit and broke the
> > unbreak/wakeup logic.
> >
> > v4: Also handle deadlocks in pin_to_display.
> >
> > Cc: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Mika Kuoppala <mika.kuoppala@intel.com>
> > Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_drv.h | 3 +++
> > drivers/gpu/drm/i915/intel_display.c | 45 +++++++++++++++++++++++++++++++-----
> > 2 files changed, 42 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 07e98b07c5bc..9b055deca36d 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1505,6 +1505,8 @@ struct i915_gpu_error {
> > /* Protected by the above dev->gpu_error.lock. */
> > struct i915_gpu_state *first_error;
> >
> > + atomic_t pending_fb_pin;
> > +
> > unsigned long missed_irq_rings;
> >
> > /**
> > @@ -1564,6 +1566,7 @@ struct i915_gpu_error {
> > unsigned long flags;
> > #define I915_RESET_BACKOFF 0
> > #define I915_RESET_HANDOFF 1
> > +#define I915_RESET_MODESET 2
> > #define I915_WEDGED (BITS_PER_LONG - 1)
> > #define I915_RESET_ENGINE (I915_WEDGED - I915_NUM_ENGINES)
> >
>
> Since you still need to resend this, could you also update the
> I915_RESET_ENGINE overflow check in i915_handle_error? i.e.:
>
> ---BUILD_BUG_ON(I915_RESET_HANDOFF >= I915_RESET_ENGINE);
> +++BUILD_BUG_ON(I915_RESET_MODESET >= I915_RESET_ENGINE);
>
> Not that we would have this problem anytime soon...
Yeah missed that, will fix.
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index f6bd6282d7f7..63ea8d6b2ebd 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2162,6 +2162,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
> > */
> > intel_runtime_pm_get(dev_priv);
> >
> > + atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
> > +
>
> Do we also need this in intel_overlay_do_put_image? It is also being called
> when the struct_mutex is held.
Indeed I missed that, will fix too and resubmit the pile (once we agree on
a comment for the previous patch).
Thanks, Daniel
>
>
> > vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
> > if (IS_ERR(vma))
> > goto err;
> > @@ -2189,6 +2191,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
> >
> > i915_vma_get(vma);
> > err:
> > + atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
> > +
> > intel_runtime_pm_put(dev_priv);
> > return vma;
> > }
> > @@ -3471,11 +3475,14 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
> > !gpu_reset_clobbers_display(dev_priv))
> > return;
> >
> > - /* We have a modeset vs reset deadlock, defensively unbreak it.
> > - *
> > - * FIXME: We can do a _lot_ better, this is just a first iteration.*/
> > - i915_gem_set_wedged(dev_priv);
> > - DRM_DEBUG_DRIVER("Wedging GPU to avoid deadlocks with pending modeset updates\n");
> > + /* We have a modeset vs reset deadlock, defensively unbreak it. */
> > + set_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
> > + wake_up_all(&dev_priv->gpu_error.wait_queue);
> > +
> > + if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
> > + DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
> > + i915_gem_set_wedged(dev_priv);
> > + }
> >
> > /*
> > * Need mode_config.mutex so that we don't
> > @@ -3570,6 +3577,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
> > drm_modeset_drop_locks(ctx);
> > drm_modeset_acquire_fini(ctx);
> > mutex_unlock(&dev->mode_config.mutex);
> > +
> > + clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
> > }
> >
> > static bool abort_flip_on_reset(struct intel_crtc *crtc)
> ^^^ this is the only reason of why we need a rebase.
>
> > @@ -12381,6 +12390,30 @@ static void intel_atomic_helper_free_state_worker(struct work_struct *work)
> > intel_atomic_helper_free_state(dev_priv);
> > }
> >
> > +static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
> > +{
> > + struct wait_queue_entry wait_fence, wait_reset;
> > + struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
> > +
> > + init_wait_entry(&wait_fence, 0);
> > + init_wait_entry(&wait_reset, 0);
> > + for (;;) {
> > + prepare_to_wait(&intel_state->commit_ready.wait,
> > + &wait_fence, TASK_UNINTERRUPTIBLE);
> > + prepare_to_wait(&dev_priv->gpu_error.wait_queue,
> > + &wait_reset, TASK_UNINTERRUPTIBLE);
> > +
> > +
> > + if (i915_sw_fence_done(&intel_state->commit_ready)
> > + || test_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags))
> > + break;
> > +
> > + schedule();
> > + }
> > + finish_wait(&intel_state->commit_ready.wait, &wait_fence);
> > + finish_wait(&dev_priv->gpu_error.wait_queue, &wait_reset);
> > +}
> > +
> > static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> > {
> > struct drm_device *dev = state->dev;
> > @@ -12394,7 +12427,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> > unsigned crtc_vblank_mask = 0;
> > int i;
> >
> > - i915_sw_fence_wait(&intel_state->commit_ready);
> > + intel_atomic_commit_fence_wait(intel_state);
> >
> > drm_atomic_helper_wait_for_dependencies(state);
> >
>
> Looks good to me.
>
> -Michel
--
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] 21+ messages in thread
* Re: [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit
2017-08-07 15:33 ` Daniel Vetter
@ 2017-08-07 17:06 ` Michel Thierry
0 siblings, 0 replies; 21+ messages in thread
From: Michel Thierry @ 2017-08-07 17:06 UTC (permalink / raw)
To: Daniel Vetter
Cc: Vetter, Daniel, Daniel Vetter, Intel Graphics Development,
Kuoppala, Mika
On 8/7/2017 8:33 AM, Daniel Vetter wrote:
> On Thu, Aug 03, 2017 at 12:44:40PM -0700, Michel Thierry wrote:
>> On 7/20/2017 10:57 AM, Daniel Vetter wrote:
>>> Blocking in a worker is ok, that's what the unbound_wq is for. And it
>>> unifies the paths between the blocking and nonblocking commit, giving
>>> me just one path where I have to implement the deadlock avoidance
>>> trickery in the next patch.
>>>
>>> I first tried to implement the following patch without this rework, but
>>> force-completing i915_sw_fence creates some serious challenges around
>>> properly cleaning things up. So wasn't a feasible short-term approach.
>>> Another approach would be to simple keep track of all pending atomic
>>> commit work items and manually queue them from the reset code. With the
>>> caveat that double-queue in case we race with the i915_sw_fence must be
>>> avoided. Given all that, taking the cost of a double schedule in atomic
>>> for the short-term fix is the best approach, but can be changed in the
>>> future of course.
>>>
>>> v2: Amend commit message (Chris).
>>>
>>> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>> Cc: Chris Wilson <chris@chris-wilson.co.uk>
>>> Cc: Mika Kuoppala <mika.kuoppala@intel.com>
>>> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
>>> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
>>> ---
>>> drivers/gpu/drm/i915/intel_display.c | 15 +++++++--------
>>> 1 file changed, 7 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 995522e40ec1..f6bd6282d7f7 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -12394,6 +12394,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>>> unsigned crtc_vblank_mask = 0;
>>> int i;
>>>
>>> + i915_sw_fence_wait(&intel_state->commit_ready);
>>> +
>>> drm_atomic_helper_wait_for_dependencies(state);
>>>
>>> if (intel_state->modeset)
>>> @@ -12561,10 +12563,7 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
>>>
>>> switch (notify) {
>>> case FENCE_COMPLETE:
>>> - if (state->base.commit_work.func)
>>> - queue_work(system_unbound_wq, &state->base.commit_work);
>>
>> I would add a small comment here, because later-on if someone has doubts
>> (and use git-blame), it won't be visible that something changed (the case
>> and break were added by the same commit).
>
> Hm, not sure what comment I should put here? Suggestions? Only thing I
> could come up with was
>
> /* we do blocking waits in the worker, nothing to do here */
>
> But not sure that adds the information you're looking for.
That sounds good to me, or maybe
"any blocking waits already handled in the worker"
But I think both are ok.
-Michel
>
>>
>>> break;
>>> -
>>> case FENCE_FREE:
>>> {
>>> struct intel_atomic_helper *helper =
>>> @@ -12668,14 +12667,14 @@ static int intel_atomic_commit(struct drm_device *dev,
>>> }
>>>
>>> drm_atomic_state_get(state);
>>> - INIT_WORK(&state->commit_work,
>>> - nonblock ? intel_atomic_commit_work : NULL);
>>> + INIT_WORK(&state->commit_work, intel_atomic_commit_work);
>>>
>>> i915_sw_fence_commit(&intel_state->commit_ready);
>>> - if (!nonblock) {
>>> - i915_sw_fence_wait(&intel_state->commit_ready);
>>> + if (nonblock)
>>> + queue_work(system_unbound_wq, &state->commit_work);
>>> + else
>>> intel_atomic_commit_tail(state);
>>> - }
>>> +
>>>
>>> return 0;
>>> }
>>
>> Reviewed-by: Michel Thierry <michel.thierry@intel.com>
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2017-08-07 17:07 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-20 17:57 [PATCH 0/7] gpu reset and page_flip removal, take 2 Daniel Vetter
2017-07-20 17:57 ` [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
2017-07-20 19:47 ` Chris Wilson
2017-07-20 20:04 ` Daniel Vetter
2017-07-20 20:16 ` Chris Wilson
2017-07-20 20:18 ` Daniel Vetter
2017-07-20 17:57 ` [PATCH 2/7] drm/i915: Push i915_sw_fence_wait into the nonblocking atomic commit Daniel Vetter
2017-08-03 19:44 ` Michel Thierry
2017-08-07 15:33 ` Daniel Vetter
2017-08-07 17:06 ` Michel Thierry
2017-07-20 17:57 ` [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock Daniel Vetter
2017-08-03 19:35 ` Michel Thierry
2017-08-07 15:39 ` Daniel Vetter
2017-07-20 17:57 ` [PATCH 4/7] drm/i915: Rip out legacy page_flip completion/irq handling Daniel Vetter
2017-07-20 17:57 ` [PATCH 5/7] drm/i915: adjust has_pending_fb_unpin to atomic Daniel Vetter
2017-07-20 17:57 ` [PATCH 6/7] drm/i915: Remove intel_flip_work infrastructure Daniel Vetter
2017-07-20 17:57 ` [PATCH 7/7] drm/i915: Drop unpin stall in atomic_prepare_commit Daniel Vetter
2017-07-20 20:47 ` Daniel Vetter
2017-07-20 18:14 ` ✓ Fi.CI.BAT: success for gpu reset and page_flip removal, take 2 Patchwork
2017-07-20 19:45 ` Chris Wilson
-- strict thread matches above, loose matches on Subject: below --
2017-07-20 11:43 [PATCH 1/7] drm/i915: Avoid the gpu reset vs. modeset deadlock Daniel Vetter
2017-07-20 11:43 ` [PATCH 3/7] drm/i915: More surgically unbreak the modeset vs reset deadlock Daniel Vetter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox