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: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1470388464-28458-3-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
b8f9096d6a
commit
8a3b3d576c
|
@ -63,32 +63,12 @@ struct i915_mmu_object {
|
|||
|
||||
static void wait_rendering(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->base.dev;
|
||||
struct drm_i915_gem_request *requests[I915_NUM_ENGINES];
|
||||
int i, n;
|
||||
unsigned long active = __I915_BO_ACTIVE(obj);
|
||||
int idx;
|
||||
|
||||
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++)
|
||||
i915_wait_request(requests[i], false, NULL, NULL);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
i915_gem_request_put(requests[i]);
|
||||
for_each_active(active, idx)
|
||||
i915_gem_active_wait_unlocked(&obj->last_read[idx],
|
||||
false, NULL, NULL);
|
||||
}
|
||||
|
||||
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_device *dev = obj->base.dev;
|
||||
|
||||
wait_rendering(obj);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
/* Cancel any active worker and force us to re-evaluate gup */
|
||||
obj->userptr.work = NULL;
|
||||
|
@ -105,8 +87,6 @@ static void cancel_userptr(struct work_struct *work)
|
|||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
bool was_interruptible;
|
||||
|
||||
wait_rendering(obj);
|
||||
|
||||
was_interruptible = dev_priv->mm.interruptible;
|
||||
dev_priv->mm.interruptible = false;
|
||||
|
||||
|
|
Loading…
Reference in New Issue