Commit 8a3b3d57 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Convert non-blocking userptr waits for requests over to using RCU

We can completely avoid taking the struct_mutex around the non-blocking
waits by switching over to the RCU request management (trading the mutex
for a RCU read lock and some complex atomic operations). The improvement
is that we gain further contention reduction, and overall the code
become simpler due to the reduced mutex dancing.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470388464-28458-3-git-send-email-chris@chris-wilson.co.uk
parent b8f9096d
...@@ -63,32 +63,12 @@ struct i915_mmu_object { ...@@ -63,32 +63,12 @@ struct i915_mmu_object {
static void wait_rendering(struct drm_i915_gem_object *obj) static void wait_rendering(struct drm_i915_gem_object *obj)
{ {
struct drm_device *dev = obj->base.dev; unsigned long active = __I915_BO_ACTIVE(obj);
struct drm_i915_gem_request *requests[I915_NUM_ENGINES]; int idx;
int i, n;
if (!i915_gem_object_is_active(obj))
return;
n = 0;
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct drm_i915_gem_request *req;
req = i915_gem_active_get(&obj->last_read[i],
&obj->base.dev->struct_mutex);
if (req)
requests[n++] = req;
}
mutex_unlock(&dev->struct_mutex);
for (i = 0; i < n; i++) for_each_active(active, idx)
i915_wait_request(requests[i], false, NULL, NULL); i915_gem_active_wait_unlocked(&obj->last_read[idx],
false, NULL, NULL);
mutex_lock(&dev->struct_mutex);
for (i = 0; i < n; i++)
i915_gem_request_put(requests[i]);
} }
static void cancel_userptr(struct work_struct *work) static void cancel_userptr(struct work_struct *work)
...@@ -97,6 +77,8 @@ static void cancel_userptr(struct work_struct *work) ...@@ -97,6 +77,8 @@ static void cancel_userptr(struct work_struct *work)
struct drm_i915_gem_object *obj = mo->obj; struct drm_i915_gem_object *obj = mo->obj;
struct drm_device *dev = obj->base.dev; struct drm_device *dev = obj->base.dev;
wait_rendering(obj);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
/* Cancel any active worker and force us to re-evaluate gup */ /* Cancel any active worker and force us to re-evaluate gup */
obj->userptr.work = NULL; obj->userptr.work = NULL;
...@@ -105,8 +87,6 @@ static void cancel_userptr(struct work_struct *work) ...@@ -105,8 +87,6 @@ static void cancel_userptr(struct work_struct *work)
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
bool was_interruptible; bool was_interruptible;
wait_rendering(obj);
was_interruptible = dev_priv->mm.interruptible; was_interruptible = dev_priv->mm.interruptible;
dev_priv->mm.interruptible = false; dev_priv->mm.interruptible = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment