summaryrefslogtreecommitdiff
path: root/drivers/dma/dmatest.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2013-11-06 16:30:09 -0800
committerDan Williams <dan.j.williams@intel.com>2013-11-14 11:04:40 -0800
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 {
struct list_head threads;
};
+static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static bool wait;
+
+static bool is_threaded_test_run(struct dmatest_info *info)
+{
+ struct dmatest_chan *dtc;
+
+ list_for_each_entry(dtc, &info->channels, node) {
+ struct dmatest_thread *thread;
+
+ list_for_each_entry(thread, &dtc->threads, node) {
+ if (!thread->done)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int dmatest_wait_get(char *val, const struct kernel_param *kp)
+{
+ struct dmatest_info *info = &test_info;
+ struct dmatest_params *params = &info->params;
+
+ if (params->iterations)
+ wait_event(thread_wait, !is_threaded_test_run(info));
+ wait = true;
+ return param_get_bool(val, kp);
+}
+
+static struct kernel_param_ops wait_ops = {
+ .get = dmatest_wait_get,
+ .set = param_set_bool,
+};
+module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
+MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
+
static bool dmatest_match_channel(struct dmatest_params *params,
struct dma_chan *chan)
{
@@ -660,12 +697,7 @@ err_thread_type:
dmaengine_terminate_all(chan);
thread->done = true;
-
- if (params->iterations > 0)
- while (!kthread_should_stop()) {
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
- interruptible_sleep_on(&wait_dmatest_exit);
- }
+ wake_up(&thread_wait);
return ret;
}
@@ -681,6 +713,7 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
pr_debug("thread %s exited with status %d\n",
thread->task->comm, ret);
list_del(&thread->node);
+ put_task_struct(thread->task);
kfree(thread);
}
@@ -719,18 +752,19 @@ static int dmatest_add_threads(struct dmatest_info *info,
thread->chan = dtc->chan;
thread->type = type;
smp_wmb();
- thread->task = kthread_run(dmatest_func, thread, "%s-%s%u",
+ thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
dma_chan_name(chan), op, i);
if (IS_ERR(thread->task)) {
- pr_warn("Failed to run thread %s-%s%u\n",
+ pr_warn("Failed to create thread %s-%s%u\n",
dma_chan_name(chan), op, i);
kfree(thread);
break;
}
/* srcbuf and dstbuf are allocated by the thread itself */
-
+ get_task_struct(thread->task);
list_add_tail(&thread->node, &dtc->threads);
+ wake_up_process(thread->task);
}
return i;
@@ -863,22 +897,6 @@ static void restart_threaded_test(struct dmatest_info *info, bool run)
run_threaded_test(info);
}
-static bool is_threaded_test_run(struct dmatest_info *info)
-{
- struct dmatest_chan *dtc;
-
- list_for_each_entry(dtc, &info->channels, node) {
- struct dmatest_thread *thread;
-
- list_for_each_entry(thread, &dtc->threads, node) {
- if (!thread->done)
- return true;
- }
- }
-
- return false;
-}
-
static int dmatest_run_get(char *val, const struct kernel_param *kp)
{
struct dmatest_info *info = &test_info;
@@ -920,6 +938,7 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
static int __init dmatest_init(void)
{
struct dmatest_info *info = &test_info;
+ struct dmatest_params *params = &info->params;
if (dmatest_run) {
mutex_lock(&info->lock);
@@ -927,6 +946,9 @@ static int __init dmatest_init(void)
mutex_unlock(&info->lock);
}
+ if (params->iterations && wait)
+ wait_event(thread_wait, !is_threaded_test_run(info));
+
/* module parameters are stable, inittime tests are started,
* let userspace take over 'run' control
*/