summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_active.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-07-26 00:38:43 +0200
committerChris Wilson <chris@chris-wilson.co.uk>2019-07-26 02:11:25 +0200
commit79c7a28e1f3a74b95ae2eae36ed0046fc8e6c7fd (patch)
tree3c6db6c855987070e2d8b9b76eb3b9c624136a3f /drivers/gpu/drm/i915/i915_active.c
parentdrm/i915/uc: Move uc firmware layout definitions to dedicated file (diff)
downloadlinux-79c7a28e1f3a74b95ae2eae36ed0046fc8e6c7fd.tar.xz
linux-79c7a28e1f3a74b95ae2eae36ed0046fc8e6c7fd.zip
drm/i915: Capture vma contents outside of spinlock
Currently we use the engine->active.lock to ensure that the request is not retired as we capture the data. However, we only need to ensure that the vma are not removed prior to use acquiring their contents, and since we have already relinquished our stop-machine protection, we assume that the user will not be overwriting the contents before we are able to record them. In order to capture the vma outside of the spinlock, we acquire a reference and mark the vma as active to prevent it from being unbound. However, since it is tricky allocate an entry in the fence tree (doing so would require taking a mutex) while inside the engine spinlock, we use an atomic bit and special case the handling for i915_active_wait. The core benefit is that we can use some non-atomic methods for mapping the device pages, we can remove the slow compression phase out of atomic context (i.e. stop antagonising the nmi-watchdog), and no we longer need large reserves of atomic pages. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111215 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190725223843.8971-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/i915_active.c')
-rw-r--r--drivers/gpu/drm/i915/i915_active.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index 13f304a29fc8..22341c62c204 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -196,6 +196,7 @@ void __i915_active_init(struct drm_i915_private *i915,
debug_active_init(ref);
ref->i915 = i915;
+ ref->flags = 0;
ref->active = active;
ref->retire = retire;
ref->tree = RB_ROOT;
@@ -262,6 +263,34 @@ void i915_active_release(struct i915_active *ref)
active_retire(ref);
}
+static void __active_ungrab(struct i915_active *ref)
+{
+ clear_and_wake_up_bit(I915_ACTIVE_GRAB_BIT, &ref->flags);
+}
+
+bool i915_active_trygrab(struct i915_active *ref)
+{
+ debug_active_assert(ref);
+
+ if (test_and_set_bit(I915_ACTIVE_GRAB_BIT, &ref->flags))
+ return false;
+
+ if (!atomic_add_unless(&ref->count, 1, 0)) {
+ __active_ungrab(ref);
+ return false;
+ }
+
+ return true;
+}
+
+void i915_active_ungrab(struct i915_active *ref)
+{
+ GEM_BUG_ON(!test_bit(I915_ACTIVE_GRAB_BIT, &ref->flags));
+
+ active_retire(ref);
+ __active_ungrab(ref);
+}
+
int i915_active_wait(struct i915_active *ref)
{
struct active_node *it, *n;
@@ -270,7 +299,7 @@ int i915_active_wait(struct i915_active *ref)
might_sleep();
might_lock(&ref->mutex);
- if (RB_EMPTY_ROOT(&ref->tree))
+ if (i915_active_is_idle(ref))
return 0;
err = mutex_lock_interruptible(&ref->mutex);
@@ -292,6 +321,9 @@ int i915_active_wait(struct i915_active *ref)
if (err)
return err;
+ if (wait_on_bit(&ref->flags, I915_ACTIVE_GRAB_BIT, TASK_KILLABLE))
+ return -EINTR;
+
if (!i915_active_is_idle(ref))
return -EBUSY;