[PATCH 4/5] dma-buf/fence-chain: Wait on each tested chain link
Janusz Krzysztofik
janusz.krzysztofik at linux.intel.com
Wed Aug 13 14:45:37 UTC 2025
Userspace may build dma_fence chains of arbitrary length step by step,
e.g. via drm_syncobj IOCTLs, and each step may start waiting on a chain
link it has added.
Adjust the wait_* selftests to cover such extreme use cases.
Signed-off-by: Janusz Krzysztofik <janusz.krzysztofik at linux.intel.com>
---
drivers/dma-buf/st-dma-fence-chain.c | 118 +++++++++++++++++++++------
1 file changed, 91 insertions(+), 27 deletions(-)
diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c
index 28763fc797c69..0e7a24ed7caeb 100644
--- a/drivers/dma-buf/st-dma-fence-chain.c
+++ b/drivers/dma-buf/st-dma-fence-chain.c
@@ -568,23 +568,34 @@ static int __wait_fence_chains(void *arg)
static int wait_forward(void *arg)
{
+ struct task_struct **tsk;
struct fence_chains fc;
- struct task_struct *tsk;
ktime_t dt;
+ int i = 0;
int err;
- int i;
err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
if (err)
return err;
- tsk = kthread_run(__wait_fence_chains, fc.tail, "dmabuf/wait");
- if (IS_ERR(tsk)) {
- err = PTR_ERR(tsk);
+ tsk = kmalloc_array(fc.chain_length, sizeof(*tsk), GFP_KERNEL);
+ if (!tsk) {
+ err = -ENOMEM;
goto err;
}
- get_task_struct(tsk);
- yield_to(tsk, true);
+
+ for (i = 0; i < fc.chain_length; i++) {
+ tsk[i] = kthread_run(__wait_fence_chains, fc.chains[i],
+ "dmabuf/wait-%llu", fc.fences[i]->seqno);
+ if (IS_ERR(tsk[i])) {
+ err = PTR_ERR(tsk[i]);
+ pr_err("Reported %d for kthread_run(%llu)!\n",
+ err, fc.fences[i]->seqno);
+ goto err;
+ }
+ get_task_struct(tsk[i]);
+ yield_to(tsk[i], true);
+ }
dt = -ktime_get();
for (i = 0; i < fc.chain_length; i++)
@@ -593,32 +604,53 @@ static int wait_forward(void *arg)
pr_info("%s: %d signals in %llu ns\n", __func__, fc.chain_length, ktime_to_ns(dt));
- err = kthread_stop_put(tsk);
-
err:
+ while (i--) {
+ int tsk_err = kthread_stop_put(tsk[i]);
+
+ if (tsk_err)
+ pr_err("Reported %d for kthread_stop_put(%llu)!\n",
+ tsk_err, fc.fences[i]->seqno);
+
+ if (!err)
+ err = tsk_err;
+ }
+ kfree(tsk);
+
fence_chains_fini(&fc);
return err;
}
static int wait_backward(void *arg)
{
+ struct task_struct **tsk;
struct fence_chains fc;
- struct task_struct *tsk;
ktime_t dt;
+ int i = 0;
int err;
- int i;
err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
if (err)
return err;
- tsk = kthread_run(__wait_fence_chains, fc.tail, "dmabuf/wait");
- if (IS_ERR(tsk)) {
- err = PTR_ERR(tsk);
+ tsk = kmalloc_array(fc.chain_length, sizeof(*tsk), GFP_KERNEL);
+ if (!tsk) {
+ err = -ENOMEM;
goto err;
}
- get_task_struct(tsk);
- yield_to(tsk, true);
+
+ for (i = 0; i < fc.chain_length; i++) {
+ tsk[i] = kthread_run(__wait_fence_chains, fc.chains[i],
+ "dmabuf/wait-%llu", fc.fences[i]->seqno);
+ if (IS_ERR(tsk[i])) {
+ err = PTR_ERR(tsk[i]);
+ pr_err("Reported %d for kthread_run(%llu)!\n",
+ err, fc.fences[i]->seqno);
+ goto err;
+ }
+ get_task_struct(tsk[i]);
+ yield_to(tsk[i], true);
+ }
dt = -ktime_get();
for (i = fc.chain_length; i--; )
@@ -627,9 +659,20 @@ static int wait_backward(void *arg)
pr_info("%s: %d signals in %llu ns\n", __func__, fc.chain_length, ktime_to_ns(dt));
- err = kthread_stop_put(tsk);
-
+ i = fc.chain_length;
err:
+ while (i--) {
+ int tsk_err = kthread_stop_put(tsk[i]);
+
+ if (tsk_err)
+ pr_err("Reported %d for kthread_stop_put(%llu)!\n",
+ tsk_err, fc.fences[i]->seqno);
+
+ if (!err)
+ err = tsk_err;
+ }
+ kfree(tsk);
+
fence_chains_fini(&fc);
return err;
}
@@ -652,11 +695,11 @@ static void randomise_fences(struct fence_chains *fc)
static int wait_random(void *arg)
{
+ struct task_struct **tsk;
struct fence_chains fc;
- struct task_struct *tsk;
ktime_t dt;
+ int i = 0;
int err;
- int i;
err = fence_chains_init(&fc, CHAIN_SZ, seqno_inc);
if (err)
@@ -664,13 +707,24 @@ static int wait_random(void *arg)
randomise_fences(&fc);
- tsk = kthread_run(__wait_fence_chains, fc.tail, "dmabuf/wait");
- if (IS_ERR(tsk)) {
- err = PTR_ERR(tsk);
+ tsk = kmalloc_array(fc.chain_length, sizeof(*tsk), GFP_KERNEL);
+ if (!tsk) {
+ err = -ENOMEM;
goto err;
}
- get_task_struct(tsk);
- yield_to(tsk, true);
+
+ for (i = 0; i < fc.chain_length; i++) {
+ tsk[i] = kthread_run(__wait_fence_chains, fc.chains[i],
+ "dmabuf/wait-%llu", fc.fences[i]->seqno);
+ if (IS_ERR(tsk[i])) {
+ err = PTR_ERR(tsk[i]);
+ pr_err("Reported %d for kthread_run(%llu)!\n",
+ err, fc.fences[i]->seqno);
+ goto err;
+ }
+ get_task_struct(tsk[i]);
+ yield_to(tsk[i], true);
+ }
dt = -ktime_get();
for (i = 0; i < fc.chain_length; i++)
@@ -679,9 +733,19 @@ static int wait_random(void *arg)
pr_info("%s: %d signals in %llu ns\n", __func__, fc.chain_length, ktime_to_ns(dt));
- err = kthread_stop_put(tsk);
-
err:
+ while (i--) {
+ int tsk_err = kthread_stop_put(tsk[i]);
+
+ if (tsk_err)
+ pr_err("Reported %d for kthread_stop_put(%llu)!\n",
+ tsk_err, fc.fences[i]->seqno);
+
+ if (!err)
+ err = tsk_err;
+ }
+ kfree(tsk);
+
fence_chains_fini(&fc);
return err;
}
--
2.50.1
More information about the Intel-gfx-trybot
mailing list