summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/gem/i915_gem_busy.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-08-14 19:24:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2019-08-16 12:40:58 +0100
commitb016cd6ed4b772759804e0d6082bd1f5ca63b8ee (patch)
tree278f8b1426b40316f5744cd6155ec51ecc9dd6c7 /drivers/gpu/drm/i915/gem/i915_gem_busy.c
parentdc2e1e5b279966affbd11ff7cfef52eb634ca2c9 (diff)
dma-buf: Restore seqlock around dma_resv updates
This reverts 67c97fb79a7f ("dma-buf: add reservation_object_fences helper") dd7a7d1ff2f1 ("drm/i915: use new reservation_object_fences helper") 0e1d8083bddb ("dma-buf: further relax reservation_object_add_shared_fence") 5d344f58da76 ("dma-buf: nuke reservation_object seq number") The scenario that defeats simply grabbing a set of shared/exclusive fences and using them blissfully under RCU is that any of those fences may be reallocated by a SLAB_TYPESAFE_BY_RCU fence slab cache. In this scenario, while keeping the rcu_read_lock we need to establish that no fence was changed in the dma_resv after a read (or full) memory barrier. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190814182401.25009-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/gem/i915_gem_busy.c')
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_busy.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index a2aff1d8290e..3d4f5775a4ba 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -83,8 +83,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_i915_gem_busy *args = data;
struct drm_i915_gem_object *obj;
struct dma_resv_list *list;
- unsigned int i, shared_count;
- struct dma_fence *excl;
+ unsigned int seq;
int err;
err = -ENOENT;
@@ -110,18 +109,29 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
* to report the overall busyness. This is what the wait-ioctl does.
*
*/
- dma_resv_fences(obj->base.resv, &excl, &list, &shared_count);
+retry:
+ seq = raw_read_seqcount(&obj->base.resv->seq);
/* Translate the exclusive fence to the READ *and* WRITE engine */
- args->busy = busy_check_writer(excl);
+ args->busy =
+ busy_check_writer(rcu_dereference(obj->base.resv->fence_excl));
/* Translate shared fences to READ set of engines */
- for (i = 0; i < shared_count; ++i) {
- struct dma_fence *fence = rcu_dereference(list->shared[i]);
+ list = rcu_dereference(obj->base.resv->fence);
+ if (list) {
+ unsigned int shared_count = list->shared_count, i;
- args->busy |= busy_check_reader(fence);
+ for (i = 0; i < shared_count; ++i) {
+ struct dma_fence *fence =
+ rcu_dereference(list->shared[i]);
+
+ args->busy |= busy_check_reader(fence);
+ }
}
+ if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
+ goto retry;
+
err = 0;
out:
rcu_read_unlock();