Skip to content

Commit 2d88ce7

Browse files
committed
dmatest: add a 'wait' parameter
Allows for scripting test runs by module load / unload. Prevent module load from returning until 'iterations' (finite) tests have completed, or cause reads of the 'wait' parameter in sysfs to pause until the tests are done. Also killed the local waitqueue since we can just let the thread exit naturally as long as we hold a reference. Cc: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 8672744 commit 2d88ce7

File tree

2 files changed

+64
-35
lines changed

2 files changed

+64
-35
lines changed

Documentation/dmatest.txt

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,24 @@ stops.
3939

4040
Note that running a new test will not stop any in progress test.
4141

42-
The following command should return actual state of the test.
43-
% cat /sys/kernel/debug/dmatest/run
42+
The following command returns the state of the test.
43+
% cat /sys/module/dmatest/parameters/run
4444

45-
To wait for test done the user may perform a busy loop that checks the state.
45+
To wait for test completion userpace can poll 'run' until it is false, or use
46+
the wait parameter. Specifying 'wait=1' when loading the module causes module
47+
initialization to pause until a test run has completed, while reading
48+
/sys/module/dmatest/parameters/wait waits for any running test to complete
49+
before returning. For example, the following scripts wait for 42 tests
50+
to complete before exiting. Note that if 'iterations' is set to 'infinite' then
51+
waiting is disabled.
4652

47-
% while [ $(cat /sys/module/dmatest/parameters/run) = "Y" ]
48-
> do
49-
> echo -n "."
50-
> sleep 1
51-
> done
52-
> echo
53+
Example:
54+
% modprobe dmatest run=1 iterations=42 wait=1
55+
% modprobe -r dmatest
56+
...or:
57+
% modprobe dmatest run=1 iterations=42
58+
% cat /sys/module/dmatest/parameters/wait
59+
% modprobe -r dmatest
5360

5461
Part 3 - When built-in in the kernel...
5562

@@ -79,7 +86,7 @@ number of tests executed, number that failed, and a result code.
7986

8087
Example:
8188
% dmesg | tail -n 1
82-
dmatest: dma3chan0-copy0: summary 400000 tests, 0 failures iops: 61524 KB/s 246098 (0)
89+
dmatest: dma0chan0-copy0: summary 1 test, 0 failures 1000 iops 100000 KB/s (0)
8390

8491
The details of a data miscompare error are also emitted, but do not follow the
8592
above format.

drivers/dma/dmatest.c

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,43 @@ struct dmatest_chan {
161161
struct list_head threads;
162162
};
163163

164+
static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
165+
static bool wait;
166+
167+
static bool is_threaded_test_run(struct dmatest_info *info)
168+
{
169+
struct dmatest_chan *dtc;
170+
171+
list_for_each_entry(dtc, &info->channels, node) {
172+
struct dmatest_thread *thread;
173+
174+
list_for_each_entry(thread, &dtc->threads, node) {
175+
if (!thread->done)
176+
return true;
177+
}
178+
}
179+
180+
return false;
181+
}
182+
183+
static int dmatest_wait_get(char *val, const struct kernel_param *kp)
184+
{
185+
struct dmatest_info *info = &test_info;
186+
struct dmatest_params *params = &info->params;
187+
188+
if (params->iterations)
189+
wait_event(thread_wait, !is_threaded_test_run(info));
190+
wait = true;
191+
return param_get_bool(val, kp);
192+
}
193+
194+
static struct kernel_param_ops wait_ops = {
195+
.get = dmatest_wait_get,
196+
.set = param_set_bool,
197+
};
198+
module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
199+
MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
200+
164201
static bool dmatest_match_channel(struct dmatest_params *params,
165202
struct dma_chan *chan)
166203
{
@@ -660,12 +697,7 @@ static int dmatest_func(void *data)
660697
dmaengine_terminate_all(chan);
661698

662699
thread->done = true;
663-
664-
if (params->iterations > 0)
665-
while (!kthread_should_stop()) {
666-
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
667-
interruptible_sleep_on(&wait_dmatest_exit);
668-
}
700+
wake_up(&thread_wait);
669701

670702
return ret;
671703
}
@@ -681,6 +713,7 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
681713
pr_debug("thread %s exited with status %d\n",
682714
thread->task->comm, ret);
683715
list_del(&thread->node);
716+
put_task_struct(thread->task);
684717
kfree(thread);
685718
}
686719

@@ -719,18 +752,19 @@ static int dmatest_add_threads(struct dmatest_info *info,
719752
thread->chan = dtc->chan;
720753
thread->type = type;
721754
smp_wmb();
722-
thread->task = kthread_run(dmatest_func, thread, "%s-%s%u",
755+
thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
723756
dma_chan_name(chan), op, i);
724757
if (IS_ERR(thread->task)) {
725-
pr_warn("Failed to run thread %s-%s%u\n",
758+
pr_warn("Failed to create thread %s-%s%u\n",
726759
dma_chan_name(chan), op, i);
727760
kfree(thread);
728761
break;
729762
}
730763

731764
/* srcbuf and dstbuf are allocated by the thread itself */
732-
765+
get_task_struct(thread->task);
733766
list_add_tail(&thread->node, &dtc->threads);
767+
wake_up_process(thread->task);
734768
}
735769

736770
return i;
@@ -863,22 +897,6 @@ static void restart_threaded_test(struct dmatest_info *info, bool run)
863897
run_threaded_test(info);
864898
}
865899

866-
static bool is_threaded_test_run(struct dmatest_info *info)
867-
{
868-
struct dmatest_chan *dtc;
869-
870-
list_for_each_entry(dtc, &info->channels, node) {
871-
struct dmatest_thread *thread;
872-
873-
list_for_each_entry(thread, &dtc->threads, node) {
874-
if (!thread->done)
875-
return true;
876-
}
877-
}
878-
879-
return false;
880-
}
881-
882900
static int dmatest_run_get(char *val, const struct kernel_param *kp)
883901
{
884902
struct dmatest_info *info = &test_info;
@@ -920,13 +938,17 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
920938
static int __init dmatest_init(void)
921939
{
922940
struct dmatest_info *info = &test_info;
941+
struct dmatest_params *params = &info->params;
923942

924943
if (dmatest_run) {
925944
mutex_lock(&info->lock);
926945
run_threaded_test(info);
927946
mutex_unlock(&info->lock);
928947
}
929948

949+
if (params->iterations && wait)
950+
wait_event(thread_wait, !is_threaded_test_run(info));
951+
930952
/* module parameters are stable, inittime tests are started,
931953
* let userspace take over 'run' control
932954
*/

0 commit comments

Comments
 (0)