On Tue, Oct 05, 2021 at 01:37:17PM +0200, 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
Yeah this is great, since if we then get some specific bug later on it's going to be very easy to add the unit test for the precise bug hopefully.
I scrolled through, looks correct.
Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
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