aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/dmatest.txt27
-rw-r--r--drivers/dma/dmatest.c72
2 files changed, 64 insertions, 35 deletions
diff --git a/Documentation/dmatest.txt b/Documentation/dmatest.txt
index 0beb4b68d81f..dd77a81bdb80 100644
--- a/Documentation/dmatest.txt
+++ b/Documentation/dmatest.txt
@@ -39,17 +39,24 @@ stops.
39 39
40Note that running a new test will not stop any in progress test. 40Note that running a new test will not stop any in progress test.
41 41
42The following command should return actual state of the test. 42The following command returns the state of the test.
43 % cat /sys/kernel/debug/dmatest/run 43 % cat /sys/module/dmatest/parameters/run
44 44
45To wait for test done the user may perform a busy loop that checks the state. 45To wait for test completion userpace can poll 'run' until it is false, or use
46the wait parameter. Specifying 'wait=1' when loading the module causes module
47initialization to pause until a test run has completed, while reading
48/sys/module/dmatest/parameters/wait waits for any running test to complete
49before returning. For example, the following scripts wait for 42 tests
50to complete before exiting. Note that if 'iterations' is set to 'infinite' then
51waiting is disabled.
46 52
47 % while [ $(cat /sys/module/dmatest/parameters/run) = "Y" ] 53Example:
48 > do 54 % modprobe dmatest run=1 iterations=42 wait=1
49 > echo -n "." 55 % modprobe -r dmatest
50 > sleep 1 56...or:
51 > done 57 % modprobe dmatest run=1 iterations=42
52 > echo 58 % cat /sys/module/dmatest/parameters/wait
59 % modprobe -r dmatest
53 60
54 Part 3 - When built-in in the kernel... 61 Part 3 - When built-in in the kernel...
55 62
@@ -79,7 +86,7 @@ number of tests executed, number that failed, and a result code.
79 86
80Example: 87Example:
81 % dmesg | tail -n 1 88 % 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)
83 90
84The details of a data miscompare error are also emitted, but do not follow the 91The details of a data miscompare error are also emitted, but do not follow the
85above format. 92above format.
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 26b502069638..dd4d84d556d5 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -161,6 +161,43 @@ struct dmatest_chan {
161 struct list_head threads; 161 struct list_head threads;
162}; 162};
163 163
164static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
165static bool wait;
166
167static 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
183static 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
194static struct kernel_param_ops wait_ops = {
195 .get = dmatest_wait_get,
196 .set = param_set_bool,
197};
198module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
199MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
200
164static bool dmatest_match_channel(struct dmatest_params *params, 201static bool dmatest_match_channel(struct dmatest_params *params,
165 struct dma_chan *chan) 202 struct dma_chan *chan)
166{ 203{
@@ -660,12 +697,7 @@ err_thread_type:
660 dmaengine_terminate_all(chan); 697 dmaengine_terminate_all(chan);
661 698
662 thread->done = true; 699 thread->done = true;
663 700 wake_up(&thread_wait);
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 }
669 701
670 return ret; 702 return ret;
671} 703}
@@ -681,6 +713,7 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
681 pr_debug("thread %s exited with status %d\n", 713 pr_debug("thread %s exited with status %d\n",
682 thread->task->comm, ret); 714 thread->task->comm, ret);
683 list_del(&thread->node); 715 list_del(&thread->node);
716 put_task_struct(thread->task);
684 kfree(thread); 717 kfree(thread);
685 } 718 }
686 719
@@ -719,18 +752,19 @@ static int dmatest_add_threads(struct dmatest_info *info,
719 thread->chan = dtc->chan; 752 thread->chan = dtc->chan;
720 thread->type = type; 753 thread->type = type;
721 smp_wmb(); 754 smp_wmb();
722 thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 755 thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
723 dma_chan_name(chan), op, i); 756 dma_chan_name(chan), op, i);
724 if (IS_ERR(thread->task)) { 757 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",
726 dma_chan_name(chan), op, i); 759 dma_chan_name(chan), op, i);
727 kfree(thread); 760 kfree(thread);
728 break; 761 break;
729 } 762 }
730 763
731 /* srcbuf and dstbuf are allocated by the thread itself */ 764 /* srcbuf and dstbuf are allocated by the thread itself */
732 765 get_task_struct(thread->task);
733 list_add_tail(&thread->node, &dtc->threads); 766 list_add_tail(&thread->node, &dtc->threads);
767 wake_up_process(thread->task);
734 } 768 }
735 769
736 return i; 770 return i;
@@ -863,22 +897,6 @@ static void restart_threaded_test(struct dmatest_info *info, bool run)
863 run_threaded_test(info); 897 run_threaded_test(info);
864} 898}
865 899
866static 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
882static int dmatest_run_get(char *val, const struct kernel_param *kp) 900static int dmatest_run_get(char *val, const struct kernel_param *kp)
883{ 901{
884 struct dmatest_info *info = &test_info; 902 struct dmatest_info *info = &test_info;
@@ -920,6 +938,7 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
920static int __init dmatest_init(void) 938static int __init dmatest_init(void)
921{ 939{
922 struct dmatest_info *info = &test_info; 940 struct dmatest_info *info = &test_info;
941 struct dmatest_params *params = &info->params;
923 942
924 if (dmatest_run) { 943 if (dmatest_run) {
925 mutex_lock(&info->lock); 944 mutex_lock(&info->lock);
@@ -927,6 +946,9 @@ static int __init dmatest_init(void)
927 mutex_unlock(&info->lock); 946 mutex_unlock(&info->lock);
928 } 947 }
929 948
949 if (params->iterations && wait)
950 wait_event(thread_wait, !is_threaded_test_run(info));
951
930 /* module parameters are stable, inittime tests are started, 952 /* module parameters are stable, inittime tests are started,
931 * let userspace take over 'run' control 953 * let userspace take over 'run' control
932 */ 954 */