Module Name: src
Committed By: riastradh
Date: Sun Dec 19 11:55:25 UTC 2021
Modified Files:
src/sys/external/bsd/drm2/dist/drm/i915: i915_drv.h
src/sys/external/bsd/drm2/dist/drm/i915/display: intel_display.c
Log Message:
i915: Rework atomic commit wakeups to work with condvars.
Lock order is intel_state->commit_ready.wait.lock then
dev_priv->atomic_commit_lock.
To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h
cvs rdiff -u -r1.4 -r1.5 \
src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h
diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.45 src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.46
--- src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h:1.45 Sun Dec 19 11:51:59 2021
+++ src/sys/external/bsd/drm2/dist/drm/i915/i915_drv.h Sun Dec 19 11:55:24 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: i915_drv.h,v 1.45 2021/12/19 11:51:59 riastradh Exp $ */
+/* $NetBSD: i915_drv.h,v 1.46 2021/12/19 11:55:24 riastradh Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
@@ -1087,6 +1087,9 @@ struct drm_i915_private {
struct drm_atomic_state *modeset_restore_state;
struct drm_modeset_acquire_ctx reset_ctx;
+ spinlock_t atomic_commit_lock;
+ drm_waitqueue_t atomic_commit_wq;
+
struct i915_ggtt ggtt; /* VM representing the global address space */
struct i915_gem_mm mm;
Index: src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c
diff -u src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c:1.4 src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c:1.5
--- src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c:1.4 Sun Dec 19 11:55:07 2021
+++ src/sys/external/bsd/drm2/dist/drm/i915/display/intel_display.c Sun Dec 19 11:55:24 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: intel_display.c,v 1.4 2021/12/19 11:55:07 riastradh Exp $ */
+/* $NetBSD: intel_display.c,v 1.5 2021/12/19 11:55:24 riastradh Exp $ */
/*
* Copyright © 2006-2007 Intel Corporation
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intel_display.c,v 1.4 2021/12/19 11:55:07 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intel_display.c,v 1.5 2021/12/19 11:55:24 riastradh Exp $");
#include "intel_display.h" /* for pipe_drmhack */
@@ -4823,9 +4823,11 @@ void intel_prepare_reset(struct drm_i915
return;
/* We have a modeset vs reset deadlock, defensively unbreak it. */
+ spin_lock(&dev_priv->atomic_commit_lock);
set_bit(I915_RESET_MODESET, &dev_priv->gt.reset.flags);
- smp_mb__after_atomic();
- wake_up_bit(&dev_priv->gt.reset.flags, I915_RESET_MODESET);
+ DRM_SPIN_WAKEUP_ALL(&dev_priv->atomic_commit_wq,
+ &dev_priv->atomic_commit_lock);
+ spin_unlock(&dev_priv->atomic_commit_lock);
if (atomic_read(&dev_priv->gpu_error.pending_fb_pin)) {
DRM_DEBUG_KMS("Modeset potentially stuck, unbreaking through wedging\n");
@@ -15271,35 +15273,43 @@ static void intel_atomic_helper_free_sta
intel_atomic_helper_free_state(dev_priv);
}
-static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
+static int
+intel_atomic_commit_fence_wake(struct i915_sw_fence_waiter *waiter,
+ unsigned mode, int flags, void *cookie)
{
-#ifdef __NetBSD__
- panic("NYI");
-#else
- struct wait_queue_entry wait_fence, wait_reset;
+ struct intel_atomic_state *intel_state = cookie;
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(bit_waitqueue(&dev_priv->gt.reset.flags,
- I915_RESET_MODESET),
- &wait_reset, TASK_UNINTERRUPTIBLE);
+ spin_lock(&dev_priv->atomic_commit_lock);
+ DRM_SPIN_WAKEUP_ALL(&dev_priv->atomic_commit_wq,
+ &dev_priv->atomic_commit_lock);
+ spin_unlock(&dev_priv->atomic_commit_lock);
+ list_del_init(&waiter->entry);
- if (i915_sw_fence_done(&intel_state->commit_ready) ||
- test_bit(I915_RESET_MODESET, &dev_priv->gt.reset.flags))
- break;
+ return 0;
+}
- schedule();
- }
- finish_wait(&intel_state->commit_ready.wait, &wait_fence);
- finish_wait(bit_waitqueue(&dev_priv->gt.reset.flags,
- I915_RESET_MODESET),
- &wait_reset);
-#endif
+static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
+ struct i915_sw_fence_waiter waiter;
+ int ret;
+
+ waiter.flags = 0;
+ waiter.func = intel_atomic_commit_fence_wake;
+ waiter.private = intel_state;
+
+ spin_lock(&intel_state->commit_ready.wait.lock);
+ list_add_tail(&waiter.entry, &intel_state->commit_ready.wait.head);
+ spin_unlock(&intel_state->commit_ready.wait.lock);
+
+ spin_lock(&dev_priv->atomic_commit_lock);
+ DRM_SPIN_WAIT_NOINTR_UNTIL(ret, &dev_priv->atomic_commit_wq,
+ &dev_priv->atomic_commit_lock,
+ (i915_sw_fence_done(&intel_state->commit_ready) ||
+ test_bit(I915_RESET_MODESET, &dev_priv->gt.reset.flags)));
+ spin_unlock(&dev_priv->atomic_commit_lock);
}
static void intel_atomic_cleanup_work(struct work_struct *work)