* [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3
@ 2021-10-06 12:36 Christian König
2021-10-06 12:36 ` [PATCH 2/2] dma-buf: add dma_resv selftest v3 Christian König
2021-10-06 12:40 ` [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Tvrtko Ursulin
0 siblings, 2 replies; 4+ messages in thread
From: Christian König @ 2021-10-06 12:36 UTC (permalink / raw)
To: linaro-mm-sig, dri-devel, linux-media, intel-gfx, daniel; +Cc: tvrtko.ursulin
A simpler version of the iterator to be used when the dma_resv object is
locked.
v2: fix index check here as well
v3: minor coding improvement, some documentation cleanup
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/dma-buf/dma-resv.c | 51 ++++++++++++++++++++++++++++++++++++++
include/linux/dma-resv.h | 20 +++++++++++++++
2 files changed, 71 insertions(+)
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index a480af9581bd..2f98caa68ae5 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -423,6 +423,57 @@ struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
}
EXPORT_SYMBOL(dma_resv_iter_next_unlocked);
+/**
+ * dma_resv_iter_first - first fence from a locked dma_resv object
+ * @cursor: cursor to record the current position
+ *
+ * Return the first fence in the dma_resv object while holding the
+ * &dma_resv.lock.
+ */
+struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
+{
+ struct dma_fence *fence;
+
+ dma_resv_assert_held(cursor->obj);
+
+ cursor->index = 0;
+ if (cursor->all_fences)
+ cursor->fences = dma_resv_shared_list(cursor->obj);
+ else
+ cursor->fences = NULL;
+
+ fence = dma_resv_excl_fence(cursor->obj);
+ if (!fence)
+ fence = dma_resv_iter_next(cursor);
+
+ cursor->is_restarted = true;
+ return fence;
+}
+EXPORT_SYMBOL_GPL(dma_resv_iter_first);
+
+/**
+ * dma_resv_iter_next - next fence from a locked dma_resv object
+ * @cursor: cursor to record the current position
+ *
+ * Return the next fences from the dma_resv object while holding the
+ * &dma_resv.lock.
+ */
+struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
+{
+ unsigned int idx;
+
+ dma_resv_assert_held(cursor->obj);
+
+ cursor->is_restarted = false;
+ if (!cursor->fences || cursor->index >= cursor->fences->shared_count)
+ return NULL;
+
+ idx = cursor->index++;
+ return rcu_dereference_protected(cursor->fences->shared[idx],
+ dma_resv_held(cursor->obj));
+}
+EXPORT_SYMBOL_GPL(dma_resv_iter_next);
+
/**
* dma_resv_copy_fences - Copy all fences from src to dst.
* @dst: the destination reservation object
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index 764138ad8583..491359cea54c 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -179,6 +179,8 @@ struct dma_resv_iter {
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor);
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor);
+struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor);
+struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor);
/**
* dma_resv_iter_begin - initialize a dma_resv_iter object
@@ -244,6 +246,24 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor)
for (fence = dma_resv_iter_first_unlocked(cursor); \
fence; fence = dma_resv_iter_next_unlocked(cursor))
+/**
+ * dma_resv_for_each_fence - fence iterator
+ * @cursor: a struct dma_resv_iter pointer
+ * @obj: a dma_resv object pointer
+ * @all_fences: true if all fences should be returned
+ * @fence: the current fence
+ *
+ * Iterate over the fences in a struct dma_resv object while holding the
+ * &dma_resv.lock. @all_fences controls if the shared fences are returned as
+ * well. The cursor initialisation is part of the iterator and the fence stays
+ * valid as long as the lock is held and so no extra reference to the fence is
+ * taken.
+ */
+#define dma_resv_for_each_fence(cursor, obj, all_fences, fence) \
+ for (dma_resv_iter_begin(cursor, obj, all_fences), \
+ fence = dma_resv_iter_first(cursor); fence; \
+ fence = dma_resv_iter_next(cursor))
+
#define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
#define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] dma-buf: add dma_resv selftest v3
2021-10-06 12:36 [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Christian König
@ 2021-10-06 12:36 ` Christian König
2021-10-06 12:54 ` Tvrtko Ursulin
2021-10-06 12:40 ` [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Tvrtko Ursulin
1 sibling, 1 reply; 4+ messages in thread
From: Christian König @ 2021-10-06 12:36 UTC (permalink / raw)
To: linaro-mm-sig, dri-devel, linux-media, intel-gfx, daniel; +Cc: tvrtko.ursulin
Just exercising a very minor subset of the functionality, but already
proven useful.
v2: add missing locking
v3: some more cleanup and consolidation, add unlocked test as well
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/dma-buf/Makefile | 3 +-
drivers/dma-buf/selftests.h | 1 +
drivers/dma-buf/st-dma-resv.c | 282 ++++++++++++++++++++++++++++++++++
3 files changed, 285 insertions(+), 1 deletion(-)
create mode 100644 drivers/dma-buf/st-dma-resv.c
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 1ef021273a06..511805dbeb75 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o
dmabuf_selftests-y := \
selftest.o \
st-dma-fence.o \
- st-dma-fence-chain.o
+ st-dma-fence-chain.o \
+ st-dma-resv.o
obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
index bc8cea67bf1e..97d73aaa31da 100644
--- a/drivers/dma-buf/selftests.h
+++ b/drivers/dma-buf/selftests.h
@@ -12,3 +12,4 @@
selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
selftest(dma_fence, dma_fence)
selftest(dma_fence_chain, dma_fence_chain)
+selftest(dma_resv, dma_resv)
diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c
new file mode 100644
index 000000000000..50d3791ccb8c
--- /dev/null
+++ b/drivers/dma-buf/st-dma-resv.c
@@ -0,0 +1,282 @@
+/* SPDX-License-Identifier: MIT */
+
+/*
+* Copyright © 2019 Intel Corporation
+* Copyright © 2021 Advanced Micro Devices, Inc.
+*/
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/dma-resv.h>
+
+#include "selftest.h"
+
+static struct spinlock fence_lock;
+
+static const char *fence_name(struct dma_fence *f)
+{
+ return "selftest";
+}
+
+static const struct dma_fence_ops fence_ops = {
+ .get_driver_name = fence_name,
+ .get_timeline_name = fence_name,
+};
+
+static struct dma_fence *alloc_fence(void)
+{
+ struct dma_fence *f;
+
+ f = kmalloc(sizeof(*f), GFP_KERNEL);
+ if (!f)
+ return NULL;
+
+ dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
+ return f;
+}
+
+static int sanitycheck(void *arg)
+{
+ struct dma_resv resv;
+ struct dma_fence *f;
+ int r;
+
+ f = alloc_fence();
+ if (!f)
+ return -ENOMEM;
+
+ dma_fence_signal(f);
+ dma_fence_put(f);
+
+ dma_resv_init(&resv);
+ r = dma_resv_lock(&resv, NULL);
+ if (r)
+ pr_err("Resv locking failed\n");
+ else
+ dma_resv_unlock(&resv);
+ dma_resv_fini(&resv);
+ return r;
+}
+
+static int test_signaling(void *arg, bool shared)
+{
+ struct dma_resv resv;
+ struct dma_fence *f;
+ int r;
+
+ f = alloc_fence();
+ if (!f)
+ return -ENOMEM;
+
+ dma_resv_init(&resv);
+ r = dma_resv_lock(&resv, NULL);
+ if (r) {
+ pr_err("Resv locking failed\n");
+ goto err_free;
+ }
+
+ if (shared) {
+ r = dma_resv_reserve_shared(&resv, 1);
+ if (r) {
+ pr_err("Resv shared slot allocation failed\n");
+ goto err_unlock;
+ }
+
+ dma_resv_add_shared_fence(&resv, f);
+ } else {
+ dma_resv_add_excl_fence(&resv, f);
+ }
+
+ if (dma_resv_test_signaled(&resv, shared)) {
+ pr_err("Resv unexpectedly signaled\n");
+ r = -EINVAL;
+ goto err_unlock;
+ }
+ dma_fence_signal(f);
+ if (!dma_resv_test_signaled(&resv, shared)) {
+ pr_err("Resv not reporting signaled\n");
+ r = -EINVAL;
+ goto err_unlock;
+ }
+err_unlock:
+ dma_resv_unlock(&resv);
+err_free:
+ dma_resv_fini(&resv);
+ dma_fence_put(f);
+ return r;
+}
+
+static int test_excl_signaling(void *arg)
+{
+ return test_signaling(arg, false);
+}
+
+static int test_shared_signaling(void *arg)
+{
+ return test_signaling(arg, true);
+}
+
+static int test_for_each(void *arg, bool shared)
+{
+ struct dma_resv_iter cursor;
+ struct dma_fence *f, *fence;
+ struct dma_resv resv;
+ int r;
+
+ f = alloc_fence();
+ if (!f)
+ return -ENOMEM;
+
+ dma_resv_init(&resv);
+ r = dma_resv_lock(&resv, NULL);
+ if (r) {
+ pr_err("Resv locking failed\n");
+ goto err_free;
+ }
+
+ if (shared) {
+ r = dma_resv_reserve_shared(&resv, 1);
+ if (r) {
+ pr_err("Resv shared slot allocation failed\n");
+ goto err_unlock;
+ }
+
+ dma_resv_add_shared_fence(&resv, f);
+ } else {
+ dma_resv_add_excl_fence(&resv, f);
+ }
+
+ r = -ENOENT;
+ dma_resv_for_each_fence(&cursor, &resv, shared, fence) {
+ if (!r) {
+ pr_err("More than one fence found\n");
+ r = -EINVAL;
+ goto err_unlock;
+ }
+ if (f != fence) {
+ pr_err("Unexpected fence\n");
+ r = -EINVAL;
+ goto err_unlock;
+ }
+ if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
+ pr_err("Unexpected fence usage\n");
+ r = -EINVAL;
+ goto err_unlock;
+ }
+ r = 0;
+ }
+ if (r) {
+ pr_err("No fence found\n");
+ goto err_unlock;
+ }
+ dma_fence_signal(f);
+err_unlock:
+ dma_resv_unlock(&resv);
+err_free:
+ dma_resv_fini(&resv);
+ dma_fence_put(f);
+ return r;
+}
+
+static int test_excl_for_each(void *arg)
+{
+ return test_for_each(arg, false);
+}
+
+static int test_shared_for_each(void *arg)
+{
+ return test_for_each(arg, false);
+}
+
+static int test_for_each_unlocked(void *arg, bool shared)
+{
+ struct dma_resv_iter cursor;
+ struct dma_fence *f, *fence;
+ struct dma_resv resv;
+ int r;
+
+ f = alloc_fence();
+ if (!f)
+ return -ENOMEM;
+
+ dma_resv_init(&resv);
+ r = dma_resv_lock(&resv, NULL);
+ if (r) {
+ pr_err("Resv locking failed\n");
+ goto err_free;
+ }
+
+ if (shared) {
+ r = dma_resv_reserve_shared(&resv, 1);
+ if (r) {
+ pr_err("Resv shared slot allocation failed\n");
+ dma_resv_unlock(&resv);
+ goto err_free;
+ }
+
+ dma_resv_add_shared_fence(&resv, f);
+ } else {
+ dma_resv_add_excl_fence(&resv, f);
+ }
+ dma_resv_unlock(&resv);
+
+ r = -ENOENT;
+ dma_resv_iter_begin(&cursor, &resv, shared);
+ dma_resv_for_each_fence_unlocked(&cursor, fence) {
+ if (!r) {
+ dma_resv_iter_end(&cursor);
+ pr_err("More than one fence found\n");
+ r = -EINVAL;
+ goto err_free;
+ }
+ if (f != fence) {
+ dma_resv_iter_end(&cursor);
+ pr_err("Unexpected fence\n");
+ r = -EINVAL;
+ goto err_free;
+ }
+ if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
+ dma_resv_iter_end(&cursor);
+ pr_err("Unexpected fence usage\n");
+ r = -EINVAL;
+ goto err_free;
+ }
+ r = 0;
+ }
+ dma_resv_iter_end(&cursor);
+ if (r) {
+ pr_err("No fence found\n");
+ goto err_free;
+ }
+ dma_fence_signal(f);
+err_free:
+ dma_resv_fini(&resv);
+ dma_fence_put(f);
+ return r;
+}
+
+static int test_excl_for_each_unlocked(void *arg)
+{
+ return test_for_each_unlocked(arg, false);
+}
+
+static int test_shared_for_each_unlocked(void *arg)
+{
+ return test_for_each_unlocked(arg, true);
+}
+
+int dma_resv(void)
+{
+ static const struct subtest tests[] = {
+ SUBTEST(sanitycheck),
+ SUBTEST(test_excl_signaling),
+ SUBTEST(test_shared_signaling),
+ SUBTEST(test_excl_for_each),
+ SUBTEST(test_shared_for_each),
+ SUBTEST(test_excl_for_each_unlocked),
+ SUBTEST(test_shared_for_each_unlocked),
+ };
+
+ spin_lock_init(&fence_lock);
+ return subtests(tests, NULL);
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3
2021-10-06 12:36 [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Christian König
2021-10-06 12:36 ` [PATCH 2/2] dma-buf: add dma_resv selftest v3 Christian König
@ 2021-10-06 12:40 ` Tvrtko Ursulin
1 sibling, 0 replies; 4+ messages in thread
From: Tvrtko Ursulin @ 2021-10-06 12:40 UTC (permalink / raw)
To: Christian König, linaro-mm-sig, dri-devel, linux-media,
intel-gfx, daniel
On 06/10/2021 13:36, Christian König wrote:
> A simpler version of the iterator to be used when the dma_resv object is
> locked.
>
> v2: fix index check here as well
> v3: minor coding improvement, some documentation cleanup
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/dma-buf/dma-resv.c | 51 ++++++++++++++++++++++++++++++++++++++
> include/linux/dma-resv.h | 20 +++++++++++++++
> 2 files changed, 71 insertions(+)
>
> diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
> index a480af9581bd..2f98caa68ae5 100644
> --- a/drivers/dma-buf/dma-resv.c
> +++ b/drivers/dma-buf/dma-resv.c
> @@ -423,6 +423,57 @@ struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
> }
> EXPORT_SYMBOL(dma_resv_iter_next_unlocked);
>
> +/**
> + * dma_resv_iter_first - first fence from a locked dma_resv object
> + * @cursor: cursor to record the current position
> + *
> + * Return the first fence in the dma_resv object while holding the
> + * &dma_resv.lock.
> + */
> +struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
> +{
> + struct dma_fence *fence;
> +
> + dma_resv_assert_held(cursor->obj);
> +
> + cursor->index = 0;
> + if (cursor->all_fences)
> + cursor->fences = dma_resv_shared_list(cursor->obj);
> + else
> + cursor->fences = NULL;
> +
> + fence = dma_resv_excl_fence(cursor->obj);
> + if (!fence)
> + fence = dma_resv_iter_next(cursor);
> +
> + cursor->is_restarted = true;
> + return fence;
> +}
> +EXPORT_SYMBOL_GPL(dma_resv_iter_first);
> +
> +/**
> + * dma_resv_iter_next - next fence from a locked dma_resv object
> + * @cursor: cursor to record the current position
> + *
> + * Return the next fences from the dma_resv object while holding the
> + * &dma_resv.lock.
> + */
> +struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
> +{
> + unsigned int idx;
> +
> + dma_resv_assert_held(cursor->obj);
> +
> + cursor->is_restarted = false;
> + if (!cursor->fences || cursor->index >= cursor->fences->shared_count)
> + return NULL;
> +
> + idx = cursor->index++;
> + return rcu_dereference_protected(cursor->fences->shared[idx],
> + dma_resv_held(cursor->obj));
> +}
> +EXPORT_SYMBOL_GPL(dma_resv_iter_next);
> +
> /**
> * dma_resv_copy_fences - Copy all fences from src to dst.
> * @dst: the destination reservation object
> diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
> index 764138ad8583..491359cea54c 100644
> --- a/include/linux/dma-resv.h
> +++ b/include/linux/dma-resv.h
> @@ -179,6 +179,8 @@ struct dma_resv_iter {
>
> struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor);
> struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor);
> +struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor);
> +struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor);
>
> /**
> * dma_resv_iter_begin - initialize a dma_resv_iter object
> @@ -244,6 +246,24 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor)
> for (fence = dma_resv_iter_first_unlocked(cursor); \
> fence; fence = dma_resv_iter_next_unlocked(cursor))
>
> +/**
> + * dma_resv_for_each_fence - fence iterator
> + * @cursor: a struct dma_resv_iter pointer
> + * @obj: a dma_resv object pointer
> + * @all_fences: true if all fences should be returned
> + * @fence: the current fence
> + *
> + * Iterate over the fences in a struct dma_resv object while holding the
> + * &dma_resv.lock. @all_fences controls if the shared fences are returned as
> + * well. The cursor initialisation is part of the iterator and the fence stays
> + * valid as long as the lock is held and so no extra reference to the fence is
> + * taken.
> + */
> +#define dma_resv_for_each_fence(cursor, obj, all_fences, fence) \
> + for (dma_resv_iter_begin(cursor, obj, all_fences), \
> + fence = dma_resv_iter_first(cursor); fence; \
> + fence = dma_resv_iter_next(cursor))
> +
> #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
> #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
>
>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Regards,
Tvrtko
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] dma-buf: add dma_resv selftest v3
2021-10-06 12:36 ` [PATCH 2/2] dma-buf: add dma_resv selftest v3 Christian König
@ 2021-10-06 12:54 ` Tvrtko Ursulin
0 siblings, 0 replies; 4+ messages in thread
From: Tvrtko Ursulin @ 2021-10-06 12:54 UTC (permalink / raw)
To: Christian König, linaro-mm-sig, dri-devel, linux-media,
intel-gfx, daniel
On 06/10/2021 13:36, Christian König wrote:
> Just exercising a very minor subset of the functionality, but already
> proven useful.
>
> v2: add missing locking
> v3: some more cleanup and consolidation, add unlocked test as well
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/dma-buf/Makefile | 3 +-
> drivers/dma-buf/selftests.h | 1 +
> drivers/dma-buf/st-dma-resv.c | 282 ++++++++++++++++++++++++++++++++++
> 3 files changed, 285 insertions(+), 1 deletion(-)
> create mode 100644 drivers/dma-buf/st-dma-resv.c
>
> diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> index 1ef021273a06..511805dbeb75 100644
> --- a/drivers/dma-buf/Makefile
> +++ b/drivers/dma-buf/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_DMABUF_SYSFS_STATS) += dma-buf-sysfs-stats.o
> dmabuf_selftests-y := \
> selftest.o \
> st-dma-fence.o \
> - st-dma-fence-chain.o
> + st-dma-fence-chain.o \
> + st-dma-resv.o
>
> obj-$(CONFIG_DMABUF_SELFTESTS) += dmabuf_selftests.o
> diff --git a/drivers/dma-buf/selftests.h b/drivers/dma-buf/selftests.h
> index bc8cea67bf1e..97d73aaa31da 100644
> --- a/drivers/dma-buf/selftests.h
> +++ b/drivers/dma-buf/selftests.h
> @@ -12,3 +12,4 @@
> selftest(sanitycheck, __sanitycheck__) /* keep first (igt selfcheck) */
> selftest(dma_fence, dma_fence)
> selftest(dma_fence_chain, dma_fence_chain)
> +selftest(dma_resv, dma_resv)
> diff --git a/drivers/dma-buf/st-dma-resv.c b/drivers/dma-buf/st-dma-resv.c
> new file mode 100644
> index 000000000000..50d3791ccb8c
> --- /dev/null
> +++ b/drivers/dma-buf/st-dma-resv.c
> @@ -0,0 +1,282 @@
> +/* SPDX-License-Identifier: MIT */
> +
> +/*
> +* Copyright © 2019 Intel Corporation
> +* Copyright © 2021 Advanced Micro Devices, Inc.
> +*/
> +
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/dma-resv.h>
> +
> +#include "selftest.h"
> +
> +static struct spinlock fence_lock;
> +
> +static const char *fence_name(struct dma_fence *f)
> +{
> + return "selftest";
> +}
> +
> +static const struct dma_fence_ops fence_ops = {
> + .get_driver_name = fence_name,
> + .get_timeline_name = fence_name,
> +};
> +
> +static struct dma_fence *alloc_fence(void)
> +{
> + struct dma_fence *f;
> +
> + f = kmalloc(sizeof(*f), GFP_KERNEL);
> + if (!f)
> + return NULL;
> +
> + dma_fence_init(f, &fence_ops, &fence_lock, 0, 0);
> + return f;
> +}
> +
> +static int sanitycheck(void *arg)
> +{
> + struct dma_resv resv;
> + struct dma_fence *f;
> + int r;
> +
> + f = alloc_fence();
> + if (!f)
> + return -ENOMEM;
> +
> + dma_fence_signal(f);
> + dma_fence_put(f);
> +
> + dma_resv_init(&resv);
> + r = dma_resv_lock(&resv, NULL);
> + if (r)
> + pr_err("Resv locking failed\n");
> + else
> + dma_resv_unlock(&resv);
> + dma_resv_fini(&resv);
> + return r;
> +}
> +
> +static int test_signaling(void *arg, bool shared)
> +{
> + struct dma_resv resv;
> + struct dma_fence *f;
> + int r;
> +
> + f = alloc_fence();
> + if (!f)
> + return -ENOMEM;
> +
> + dma_resv_init(&resv);
> + r = dma_resv_lock(&resv, NULL);
> + if (r) {
> + pr_err("Resv locking failed\n");
> + goto err_free;
> + }
> +
> + if (shared) {
> + r = dma_resv_reserve_shared(&resv, 1);
> + if (r) {
> + pr_err("Resv shared slot allocation failed\n");
> + goto err_unlock;
> + }
> +
> + dma_resv_add_shared_fence(&resv, f);
> + } else {
> + dma_resv_add_excl_fence(&resv, f);
> + }
> +
> + if (dma_resv_test_signaled(&resv, shared)) {
> + pr_err("Resv unexpectedly signaled\n");
> + r = -EINVAL;
> + goto err_unlock;
> + }
> + dma_fence_signal(f);
> + if (!dma_resv_test_signaled(&resv, shared)) {
> + pr_err("Resv not reporting signaled\n");
> + r = -EINVAL;
> + goto err_unlock;
> + }
> +err_unlock:
> + dma_resv_unlock(&resv);
> +err_free:
> + dma_resv_fini(&resv);
> + dma_fence_put(f);
> + return r;
> +}
> +
> +static int test_excl_signaling(void *arg)
> +{
> + return test_signaling(arg, false);
> +}
> +
> +static int test_shared_signaling(void *arg)
> +{
> + return test_signaling(arg, true);
> +}
> +
> +static int test_for_each(void *arg, bool shared)
> +{
> + struct dma_resv_iter cursor;
> + struct dma_fence *f, *fence;
> + struct dma_resv resv;
> + int r;
> +
> + f = alloc_fence();
> + if (!f)
> + return -ENOMEM;
> +
> + dma_resv_init(&resv);
> + r = dma_resv_lock(&resv, NULL);
> + if (r) {
> + pr_err("Resv locking failed\n");
> + goto err_free;
> + }
> +
> + if (shared) {
> + r = dma_resv_reserve_shared(&resv, 1);
> + if (r) {
> + pr_err("Resv shared slot allocation failed\n");
> + goto err_unlock;
> + }
> +
> + dma_resv_add_shared_fence(&resv, f);
> + } else {
> + dma_resv_add_excl_fence(&resv, f);
> + }
This block repeates three times so could be consolidated but it doesn't
matter hugely.
> +
> + r = -ENOENT;
> + dma_resv_for_each_fence(&cursor, &resv, shared, fence) {
> + if (!r) {
> + pr_err("More than one fence found\n");
> + r = -EINVAL;
> + goto err_unlock;
> + }
> + if (f != fence) {
> + pr_err("Unexpected fence\n");
> + r = -EINVAL;
> + goto err_unlock;
> + }
> + if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
> + pr_err("Unexpected fence usage\n");
> + r = -EINVAL;
> + goto err_unlock;
> + }
> + r = 0;
> + }
> + if (r) {
> + pr_err("No fence found\n");
> + goto err_unlock;
> + }
> + dma_fence_signal(f);
This would warn if the loop jumps to err_unlock but I guess there are
bigger problems in that case.
> +err_unlock:
> + dma_resv_unlock(&resv);
> +err_free:
> + dma_resv_fini(&resv);
> + dma_fence_put(f);
> + return r;
> +}
> +
> +static int test_excl_for_each(void *arg)
> +{
> + return test_for_each(arg, false);
> +}
> +
> +static int test_shared_for_each(void *arg)
> +{
> + return test_for_each(arg, false);
true
With that:
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Regards,
Tvrtko
> +}
> +
> +static int test_for_each_unlocked(void *arg, bool shared)
> +{
> + struct dma_resv_iter cursor;
> + struct dma_fence *f, *fence;
> + struct dma_resv resv;
> + int r;
> +
> + f = alloc_fence();
> + if (!f)
> + return -ENOMEM;
> +
> + dma_resv_init(&resv);
> + r = dma_resv_lock(&resv, NULL);
> + if (r) {
> + pr_err("Resv locking failed\n");
> + goto err_free;
> + }
> +
> + if (shared) {
> + r = dma_resv_reserve_shared(&resv, 1);
> + if (r) {
> + pr_err("Resv shared slot allocation failed\n");
> + dma_resv_unlock(&resv);
> + goto err_free;
> + }
> +
> + dma_resv_add_shared_fence(&resv, f);
> + } else {
> + dma_resv_add_excl_fence(&resv, f);
> + }
> + dma_resv_unlock(&resv);
> +
> + r = -ENOENT;
> + dma_resv_iter_begin(&cursor, &resv, shared);
> + dma_resv_for_each_fence_unlocked(&cursor, fence) {
> + if (!r) {
> + dma_resv_iter_end(&cursor);
> + pr_err("More than one fence found\n");
> + r = -EINVAL;
> + goto err_free;
> + }
> + if (f != fence) {
> + dma_resv_iter_end(&cursor);
> + pr_err("Unexpected fence\n");
> + r = -EINVAL;
> + goto err_free;
> + }
> + if (dma_resv_iter_is_exclusive(&cursor) != !shared) {
> + dma_resv_iter_end(&cursor);
> + pr_err("Unexpected fence usage\n");
> + r = -EINVAL;
> + goto err_free;
> + }
> + r = 0;
> + }
> + dma_resv_iter_end(&cursor);
> + if (r) {
> + pr_err("No fence found\n");
> + goto err_free;
> + }
> + dma_fence_signal(f);
> +err_free:
> + dma_resv_fini(&resv);
> + dma_fence_put(f);
> + return r;
> +}
> +
> +static int test_excl_for_each_unlocked(void *arg)
> +{
> + return test_for_each_unlocked(arg, false);
> +}
> +
> +static int test_shared_for_each_unlocked(void *arg)
> +{
> + return test_for_each_unlocked(arg, true);
> +}
> +
> +int dma_resv(void)
> +{
> + static const struct subtest tests[] = {
> + SUBTEST(sanitycheck),
> + SUBTEST(test_excl_signaling),
> + SUBTEST(test_shared_signaling),
> + SUBTEST(test_excl_for_each),
> + SUBTEST(test_shared_for_each),
> + SUBTEST(test_excl_for_each_unlocked),
> + SUBTEST(test_shared_for_each_unlocked),
> + };
> +
> + spin_lock_init(&fence_lock);
> + return subtests(tests, NULL);
> +}
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-10-06 12:54 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-10-06 12:36 [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Christian König
2021-10-06 12:36 ` [PATCH 2/2] dma-buf: add dma_resv selftest v3 Christian König
2021-10-06 12:54 ` Tvrtko Ursulin
2021-10-06 12:40 ` [PATCH 1/2] dma-buf: add dma_resv_for_each_fence v3 Tvrtko Ursulin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox