diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2020-03-06 16:38:36 +0300 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2020-03-07 03:05:54 +0300 |
commit | e3e7aeec3281af446d7410d6982020e1aa5795fc (patch) | |
tree | ff02d22ad614fc5bea5aaf37ab8f424ee7cb8635 /drivers/gpu/drm/i915/selftests/i915_active.c | |
parent | dff2a11b065c552979d9e9ff1a00ff57cbc26ce7 (diff) | |
download | linux-e3e7aeec3281af446d7410d6982020e1aa5795fc.tar.xz |
drm/i915/selftests: Apply a heavy handed flush to i915_active
Due to the ordering of cmpxchg()/dma_fence_signal() inside node_retire(),
we must also use the xchg() as our primary memory barrier to flush the
outstanding callbacks after expected completion of the i915_active.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200306133852.3420322-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/selftests/i915_active.c')
-rw-r--r-- | drivers/gpu/drm/i915/selftests/i915_active.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index 3a37c67ab6c4..68bbb1580162 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -311,20 +311,33 @@ static void spin_unlock_wait(spinlock_t *lock) spin_unlock_irq(lock); } +static void active_flush(struct i915_active *ref, + struct i915_active_fence *active) +{ + struct dma_fence *fence; + + fence = xchg(__active_fence_slot(active), NULL); + if (!fence) + return; + + spin_lock_irq(fence->lock); + __list_del_entry(&active->cb.node); + spin_unlock_irq(fence->lock); /* serialise with fence->cb_list */ + atomic_dec(&ref->count); + + GEM_BUG_ON(!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)); +} + void i915_active_unlock_wait(struct i915_active *ref) { if (i915_active_acquire_if_busy(ref)) { struct active_node *it, *n; + /* Wait for all active callbacks */ rcu_read_lock(); - rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) { - struct dma_fence *f; - - /* Wait for all active callbacks */ - f = rcu_dereference(it->base.fence); - if (f) - spin_unlock_wait(f->lock); - } + active_flush(ref, &ref->excl); + rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) + active_flush(ref, &it->base); rcu_read_unlock(); i915_active_release(ref); |