aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dmatest.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2013-11-06 19:30:09 -0500
committerDan Williams <dan.j.williams@intel.com>2013-11-14 14:04:40 -0500
commit2d88ce76eb98c4ac4411dcb299cf61ca8999d2b9 (patch)
tree2422e0f7dcb01fdc596c8806174c69508aad2540 /drivers/dma/dmatest.c
parent86727443a04fdb25397041188efd2527f2b7237b (diff)
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>
Diffstat (limited to 'drivers/dma/dmatest.c')
-rw-r--r--drivers/dma/dmatest.c72
1 files changed, 47 insertions, 25 deletions
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 */