@@ -199,7 +199,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
struct reservation_object_list *fobj;
struct dma_fence *fence_excl;
__poll_t events;
- unsigned shared_count, seq;
+ unsigned shared_count;
dmabuf = file->private_data;
if (!dmabuf || !dmabuf->resv)
@@ -214,16 +214,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
return 0;
retry:
- seq = read_seqcount_begin(&resv->seq);
rcu_read_lock();
+ fence_excl = rcu_dereference(resv->fence_excl);
fobj = rcu_dereference(resv->fence);
if (fobj)
shared_count = fobj->shared_count;
else
shared_count = 0;
- fence_excl = rcu_dereference(resv->fence_excl);
- if (read_seqcount_retry(&resv->seq, seq)) {
+
+ if (rcu_dereference(resv->fence_excl) != fence_excl) {
rcu_read_unlock();
goto retry;
}
@@ -1157,7 +1157,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
struct reservation_object *robj;
struct reservation_object_list *fobj;
struct dma_fence *fence;
- unsigned seq;
int count = 0, attach_count, shared_count, i;
size_t size = 0;
@@ -1189,12 +1188,11 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
robj = buf_obj->resv;
while (true) {
- seq = read_seqcount_begin(&robj->seq);
rcu_read_lock();
+ fence = rcu_dereference(robj->fence_excl);
fobj = rcu_dereference(robj->fence);
shared_count = fobj ? fobj->shared_count : 0;
- fence = rcu_dereference(robj->fence_excl);
- if (!read_seqcount_retry(&robj->seq, seq))
+ if (rcu_dereference(robj->fence_excl) != fence)
break;
rcu_read_unlock();
}
@@ -49,12 +49,6 @@
DEFINE_WD_CLASS(reservation_ww_class);
EXPORT_SYMBOL(reservation_ww_class);
-struct lock_class_key reservation_seqcount_class;
-EXPORT_SYMBOL(reservation_seqcount_class);
-
-const char reservation_seqcount_string[] = "reservation_seqcount";
-EXPORT_SYMBOL(reservation_seqcount_string);
-
/**
* reservation_object_init - initialize a reservation object
* @obj: the reservation object
@@ -62,9 +56,6 @@ EXPORT_SYMBOL(reservation_seqcount_string);
void reservation_object_init(struct reservation_object *obj)
{
ww_mutex_init(&obj->lock, &reservation_ww_class);
-
- __seqcount_init(&obj->seq, reservation_seqcount_string,
- &reservation_seqcount_class);
RCU_INIT_POINTER(obj->fence, NULL);
RCU_INIT_POINTER(obj->fence_excl, NULL);
}
@@ -251,12 +242,10 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
dma_fence_get(fence);
preempt_disable();
- write_seqcount_begin(&obj->seq);
- /* write_seqcount_begin provides the necessary memory barrier */
RCU_INIT_POINTER(obj->fence_excl, fence);
+ /* pointer update must be visible before we modify the shared_count */
if (old)
- old->shared_count = 0;
- write_seqcount_end(&obj->seq);
+ smp_store_mb(old->shared_count, 0);
preempt_enable();
/* inplace update, no shared fences */
@@ -340,11 +329,8 @@ int reservation_object_copy_fences(struct reservation_object *dst,
old = reservation_object_get_excl(dst);
preempt_disable();
- write_seqcount_begin(&dst->seq);
- /* write_seqcount_begin provides the necessary memory barrier */
RCU_INIT_POINTER(dst->fence_excl, new);
- RCU_INIT_POINTER(dst->fence, dst_list);
- write_seqcount_end(&dst->seq);
+ rcu_assign_pointer(dst->fence, dst_list);
preempt_enable();
if (src_list)
@@ -380,18 +366,14 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
do {
struct reservation_object_list *fobj;
- unsigned int i, seq;
+ unsigned int i;
size_t sz = 0;
shared_count = i = 0;
rcu_read_lock();
- seq = read_seqcount_begin(&obj->seq);
-
- fence_excl = rcu_dereference(obj->fence_excl);
- if (fence_excl && !dma_fence_get_rcu(fence_excl))
- goto unlock;
+ fence_excl = dma_fence_get_rcu_safe(&obj->fence_excl);
fobj = rcu_dereference(obj->fence);
if (fobj)
sz += sizeof(*shared) * fobj->shared_max;
@@ -428,7 +410,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
}
}
- if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
+ if (i != shared_count ||
+ rcu_dereference(obj->fence_excl) != fence_excl) {
while (i--)
dma_fence_put(shared[i]);
dma_fence_put(fence_excl);
@@ -472,18 +455,17 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
bool wait_all, bool intr,
unsigned long timeout)
{
- struct dma_fence *fence;
- unsigned seq, shared_count;
+ struct dma_fence *fence, *fence_excl;
long ret = timeout ? timeout : 1;
+ unsigned shared_count;
int i;
retry:
shared_count = 0;
- seq = read_seqcount_begin(&obj->seq);
rcu_read_lock();
i = -1;
- fence = rcu_dereference(obj->fence_excl);
+ fence = fence_excl = rcu_dereference(obj->fence_excl);
if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
if (!dma_fence_get_rcu(fence))
goto unlock_retry;
@@ -524,13 +506,13 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
}
}
+ if (rcu_dereference(obj->fence_excl) != fence_excl) {
+ dma_fence_put(fence);
+ goto unlock_retry;
+ }
+
rcu_read_unlock();
if (fence) {
- if (read_seqcount_retry(&obj->seq, seq)) {
- dma_fence_put(fence);
- goto retry;
- }
-
ret = dma_fence_wait_timeout(fence, intr, ret);
dma_fence_put(fence);
if (ret > 0 && wait_all && (i + 1 < shared_count))
@@ -575,14 +557,15 @@ reservation_object_test_signaled_single(struct dma_fence *passed_fence)
bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
bool test_all)
{
- unsigned seq, shared_count;
+ struct dma_fence *fence_excl;
+ unsigned shared_count;
int ret;
rcu_read_lock();
retry:
+ fence_excl = rcu_dereference(obj->fence_excl);
ret = true;
shared_count = 0;
- seq = read_seqcount_begin(&obj->seq);
if (test_all) {
unsigned i;
@@ -603,12 +586,11 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
break;
}
- if (read_seqcount_retry(&obj->seq, seq))
+ if (rcu_dereference(obj->fence_excl) != fence_excl)
goto retry;
}
if (!shared_count) {
- struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
if (fence_excl) {
ret = reservation_object_test_signaled_single(
@@ -616,7 +598,7 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
if (ret < 0)
goto retry;
- if (read_seqcount_retry(&obj->seq, seq))
+ if (rcu_dereference(obj->fence_excl) != fence_excl)
goto retry;
}
}
@@ -251,12 +251,8 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
new->shared_max = old->shared_max;
new->shared_count = k;
- /* Install the new fence list, seqcount provides the barriers */
- preempt_disable();
- write_seqcount_begin(&resv->seq);
- RCU_INIT_POINTER(resv->fence, new);
- write_seqcount_end(&resv->seq);
- preempt_enable();
+ /* Install the new fence list */
+ rcu_assign_pointer(resv->fence, new);
/* Drop the references to the removed fences or move them to ef_list */
for (i = j, k = 0; i < old->shared_count; ++i) {
@@ -83,7 +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 reservation_object_list *list;
- unsigned int seq;
+ struct dma_fence *fence_excl;
int err;
err = -ENOENT;
@@ -110,11 +110,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
*
*/
retry:
- seq = raw_read_seqcount(&obj->base.resv->seq);
-
/* Translate the exclusive fence to the READ *and* WRITE engine */
- args->busy =
- busy_check_writer(rcu_dereference(obj->base.resv->fence_excl));
+ fence_excl = rcu_dereference(obj->base.resv->fence_excl);
+ args->busy = busy_check_writer(fence_excl);
/* Translate shared fences to READ set of engines */
list = rcu_dereference(obj->base.resv->fence);
@@ -129,7 +127,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
}
}
- if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
+ if (args->busy &&
+ rcu_dereference(obj->base.resv->fence_excl) != fence_excl)
goto retry;
err = 0;
@@ -46,8 +46,6 @@
#include <linux/rcupdate.h>
extern struct ww_class reservation_ww_class;
-extern struct lock_class_key reservation_seqcount_class;
-extern const char reservation_seqcount_string[];
/**
* struct reservation_object_list - a list of shared fences
@@ -71,7 +69,6 @@ struct reservation_object_list {
*/
struct reservation_object {
struct ww_mutex lock;
- seqcount_t seq;
struct dma_fence __rcu *fence_excl;
struct reservation_object_list __rcu *fence;
The only remaining use for this is to protect against setting a new exclusive fence while we grab both exclusive and shared. That can also be archived by looking if the exclusive fence has changed or not after completing the operation. Signed-off-by: Christian König <christian.koenig@amd.com> --- drivers/dma-buf/dma-buf.c | 14 ++--- drivers/dma-buf/reservation.c | 58 +++++++------------ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 8 +-- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 11 ++-- include/linux/reservation.h | 3 - 5 files changed, 33 insertions(+), 61 deletions(-)