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)