Merge tag 'f2fs-for-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[linux-2.6-block.git] / drivers / dma / dmatest.c
CommitLineData
4a776f0a
HS
1/*
2 * DMA Engine test module
3 *
4 * Copyright (C) 2007 Atmel Corporation
851b7e16 5 * Copyright (C) 2013 Intel Corporation
4a776f0a
HS
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
872f05c6
DW
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
4a776f0a 13#include <linux/delay.h>
b7f080cf 14#include <linux/dma-mapping.h>
4a776f0a 15#include <linux/dmaengine.h>
981ed70d 16#include <linux/freezer.h>
4a776f0a
HS
17#include <linux/init.h>
18#include <linux/kthread.h>
0881e7bd 19#include <linux/sched/task.h>
4a776f0a
HS
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/random.h>
5a0e3ad6 23#include <linux/slab.h>
4a776f0a
HS
24#include <linux/wait.h>
25
26static unsigned int test_buf_size = 16384;
a6c268d0 27module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
4a776f0a
HS
28MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
29
a85159fe 30static char test_device[32];
a6c268d0
AS
31module_param_string(device, test_device, sizeof(test_device),
32 S_IRUGO | S_IWUSR);
4a776f0a
HS
33MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
34
35static unsigned int threads_per_chan = 1;
a6c268d0 36module_param(threads_per_chan, uint, S_IRUGO | S_IWUSR);
4a776f0a
HS
37MODULE_PARM_DESC(threads_per_chan,
38 "Number of threads to start per channel (default: 1)");
39
40static unsigned int max_channels;
a6c268d0 41module_param(max_channels, uint, S_IRUGO | S_IWUSR);
33df8ca0 42MODULE_PARM_DESC(max_channels,
4a776f0a
HS
43 "Maximum number of channels to use (default: all)");
44
0a2ff57d 45static unsigned int iterations;
a6c268d0 46module_param(iterations, uint, S_IRUGO | S_IWUSR);
0a2ff57d
NF
47MODULE_PARM_DESC(iterations,
48 "Iterations before stopping test (default: infinite)");
49
d8646724 50static unsigned int dmatest;
a0d4cb44
KA
51module_param(dmatest, uint, S_IRUGO | S_IWUSR);
52MODULE_PARM_DESC(dmatest,
c678fa66 53 "dmatest 0-memcpy 1-memset (default: 0)");
a0d4cb44 54
b54d5cb9 55static unsigned int xor_sources = 3;
a6c268d0 56module_param(xor_sources, uint, S_IRUGO | S_IWUSR);
b54d5cb9
DW
57MODULE_PARM_DESC(xor_sources,
58 "Number of xor source buffers (default: 3)");
59
58691d64 60static unsigned int pq_sources = 3;
a6c268d0 61module_param(pq_sources, uint, S_IRUGO | S_IWUSR);
58691d64
DW
62MODULE_PARM_DESC(pq_sources,
63 "Number of p+q source buffers (default: 3)");
64
d42efe6b 65static int timeout = 3000;
a6c268d0 66module_param(timeout, uint, S_IRUGO | S_IWUSR);
85ee7a1d
JP
67MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
68 "Pass -1 for infinite timeout");
d42efe6b 69
e3b9c347
DW
70static bool noverify;
71module_param(noverify, bool, S_IRUGO | S_IWUSR);
2e67a087
YS
72MODULE_PARM_DESC(noverify, "Disable data verification (default: verify)");
73
74static bool norandom;
75module_param(norandom, bool, 0644);
76MODULE_PARM_DESC(norandom, "Disable random offset setup (default: random)");
4a776f0a 77
50137a7d
DW
78static bool verbose;
79module_param(verbose, bool, S_IRUGO | S_IWUSR);
80MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
4a776f0a 81
a875abfa
SA
82static int alignment = -1;
83module_param(alignment, int, 0644);
84MODULE_PARM_DESC(alignment, "Custom data address alignment taken as 2^(alignment) (default: not used (-1))");
85
13396a13
SA
86static unsigned int transfer_size;
87module_param(transfer_size, uint, 0644);
88MODULE_PARM_DESC(transfer_size, "Optional custom transfer size in bytes (default: not used (0))");
89
e03e93a9 90/**
15b8a8ea 91 * struct dmatest_params - test parameters.
e03e93a9
AS
92 * @buf_size: size of the memcpy test buffer
93 * @channel: bus ID of the channel to test
94 * @device: bus ID of the DMA Engine to test
95 * @threads_per_chan: number of threads to start per channel
96 * @max_channels: maximum number of channels to use
97 * @iterations: iterations before stopping test
98 * @xor_sources: number of xor source buffers
99 * @pq_sources: number of p+q source buffers
100 * @timeout: transfer timeout in msec, -1 for infinite timeout
101 */
15b8a8ea 102struct dmatest_params {
e03e93a9
AS
103 unsigned int buf_size;
104 char channel[20];
a85159fe 105 char device[32];
e03e93a9
AS
106 unsigned int threads_per_chan;
107 unsigned int max_channels;
108 unsigned int iterations;
109 unsigned int xor_sources;
110 unsigned int pq_sources;
111 int timeout;
e3b9c347 112 bool noverify;
2e67a087 113 bool norandom;
a875abfa 114 int alignment;
13396a13 115 unsigned int transfer_size;
15b8a8ea
AS
116};
117
118/**
119 * struct dmatest_info - test information.
120 * @params: test parameters
851b7e16 121 * @lock: access protection to the fields of this structure
15b8a8ea 122 */
a310d037 123static struct dmatest_info {
15b8a8ea
AS
124 /* Test parameters */
125 struct dmatest_params params;
838cc704
AS
126
127 /* Internal state */
128 struct list_head channels;
129 unsigned int nr_channels;
851b7e16 130 struct mutex lock;
a310d037
DW
131 bool did_init;
132} test_info = {
133 .channels = LIST_HEAD_INIT(test_info.channels),
134 .lock = __MUTEX_INITIALIZER(test_info.lock),
135};
851b7e16 136
a310d037
DW
137static int dmatest_run_set(const char *val, const struct kernel_param *kp);
138static int dmatest_run_get(char *val, const struct kernel_param *kp);
9c27847d 139static const struct kernel_param_ops run_ops = {
a310d037
DW
140 .set = dmatest_run_set,
141 .get = dmatest_run_get,
e03e93a9 142};
a310d037
DW
143static bool dmatest_run;
144module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR);
145MODULE_PARM_DESC(run, "Run the test (default: false)");
e03e93a9 146
d53513d5
SA
147static int dmatest_chan_set(const char *val, const struct kernel_param *kp);
148static int dmatest_chan_get(char *val, const struct kernel_param *kp);
149static const struct kernel_param_ops multi_chan_ops = {
150 .set = dmatest_chan_set,
151 .get = dmatest_chan_get,
152};
153
154static char test_channel[20];
155static struct kparam_string newchan_kps = {
156 .string = test_channel,
157 .maxlen = 20,
158};
159module_param_cb(channel, &multi_chan_ops, &newchan_kps, 0644);
160MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
161
162static int dmatest_test_list_get(char *val, const struct kernel_param *kp);
163static const struct kernel_param_ops test_list_ops = {
164 .get = dmatest_test_list_get,
165};
166module_param_cb(test_list, &test_list_ops, NULL, 0444);
167MODULE_PARM_DESC(test_list, "Print current test list");
168
a310d037
DW
169/* Maximum amount of mismatched bytes in buffer to print */
170#define MAX_ERROR_COUNT 32
171
172/*
173 * Initialization patterns. All bytes in the source buffer has bit 7
174 * set, all bytes in the destination buffer has bit 7 cleared.
175 *
176 * Bit 6 is set for all bytes which are to be copied by the DMA
177 * engine. Bit 5 is set for all bytes which are to be overwritten by
178 * the DMA engine.
179 *
180 * The remaining bits are the inverse of a counter which increments by
181 * one for each byte address.
182 */
183#define PATTERN_SRC 0x80
184#define PATTERN_DST 0x00
185#define PATTERN_COPY 0x40
186#define PATTERN_OVERWRITE 0x20
187#define PATTERN_COUNT_MASK 0x1f
61b5f54d 188#define PATTERN_MEMSET_IDX 0x01
851b7e16 189
6138f967
SA
190/* Fixed point arithmetic ops */
191#define FIXPT_SHIFT 8
192#define FIXPNT_MASK 0xFF
193#define FIXPT_TO_INT(a) ((a) >> FIXPT_SHIFT)
194#define INT_TO_FIXPT(a) ((a) << FIXPT_SHIFT)
195#define FIXPT_GET_FRAC(a) ((((a) & FIXPNT_MASK) * 100) >> FIXPT_SHIFT)
196
6f6a23a2
AW
197/* poor man's completion - we want to use wait_event_freezable() on it */
198struct dmatest_done {
199 bool done;
200 wait_queue_head_t *wait;
201};
202
361deb72
AA
203struct dmatest_data {
204 u8 **raw;
205 u8 **aligned;
206 unsigned int cnt;
207 unsigned int off;
208};
209
a310d037
DW
210struct dmatest_thread {
211 struct list_head node;
212 struct dmatest_info *info;
213 struct task_struct *task;
214 struct dma_chan *chan;
361deb72
AA
215 struct dmatest_data src;
216 struct dmatest_data dst;
a310d037 217 enum dma_transaction_type type;
6f6a23a2
AW
218 wait_queue_head_t done_wait;
219 struct dmatest_done test_done;
a310d037 220 bool done;
d53513d5 221 bool pending;
a310d037 222};
95019c8c 223
a310d037
DW
224struct dmatest_chan {
225 struct list_head node;
226 struct dma_chan *chan;
227 struct list_head threads;
e03e93a9
AS
228};
229
2d88ce76
DW
230static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
231static bool wait;
232
233static bool is_threaded_test_run(struct dmatest_info *info)
234{
235 struct dmatest_chan *dtc;
236
237 list_for_each_entry(dtc, &info->channels, node) {
238 struct dmatest_thread *thread;
239
240 list_for_each_entry(thread, &dtc->threads, node) {
241 if (!thread->done)
242 return true;
243 }
244 }
245
246 return false;
247}
248
d53513d5
SA
249static bool is_threaded_test_pending(struct dmatest_info *info)
250{
251 struct dmatest_chan *dtc;
252
253 list_for_each_entry(dtc, &info->channels, node) {
254 struct dmatest_thread *thread;
255
256 list_for_each_entry(thread, &dtc->threads, node) {
257 if (thread->pending)
258 return true;
259 }
260 }
261
262 return false;
263}
264
2d88ce76
DW
265static int dmatest_wait_get(char *val, const struct kernel_param *kp)
266{
267 struct dmatest_info *info = &test_info;
268 struct dmatest_params *params = &info->params;
269
270 if (params->iterations)
271 wait_event(thread_wait, !is_threaded_test_run(info));
272 wait = true;
273 return param_get_bool(val, kp);
274}
275
9c27847d 276static const struct kernel_param_ops wait_ops = {
2d88ce76
DW
277 .get = dmatest_wait_get,
278 .set = param_set_bool,
279};
280module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
281MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
e03e93a9 282
15b8a8ea 283static bool dmatest_match_channel(struct dmatest_params *params,
e03e93a9 284 struct dma_chan *chan)
4a776f0a 285{
15b8a8ea 286 if (params->channel[0] == '\0')
4a776f0a 287 return true;
15b8a8ea 288 return strcmp(dma_chan_name(chan), params->channel) == 0;
4a776f0a
HS
289}
290
15b8a8ea 291static bool dmatest_match_device(struct dmatest_params *params,
e03e93a9 292 struct dma_device *device)
4a776f0a 293{
15b8a8ea 294 if (params->device[0] == '\0')
4a776f0a 295 return true;
15b8a8ea 296 return strcmp(dev_name(device->dev), params->device) == 0;
4a776f0a
HS
297}
298
299static unsigned long dmatest_random(void)
300{
301 unsigned long buf;
302
be9fa5a4 303 prandom_bytes(&buf, sizeof(buf));
4a776f0a
HS
304 return buf;
305}
306
61b5f54d
SK
307static inline u8 gen_inv_idx(u8 index, bool is_memset)
308{
309 u8 val = is_memset ? PATTERN_MEMSET_IDX : index;
310
311 return ~val & PATTERN_COUNT_MASK;
312}
313
314static inline u8 gen_src_value(u8 index, bool is_memset)
315{
316 return PATTERN_SRC | gen_inv_idx(index, is_memset);
317}
318
319static inline u8 gen_dst_value(u8 index, bool is_memset)
320{
321 return PATTERN_DST | gen_inv_idx(index, is_memset);
322}
323
e03e93a9 324static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len,
61b5f54d 325 unsigned int buf_size, bool is_memset)
4a776f0a
HS
326{
327 unsigned int i;
b54d5cb9
DW
328 u8 *buf;
329
330 for (; (buf = *bufs); bufs++) {
331 for (i = 0; i < start; i++)
61b5f54d 332 buf[i] = gen_src_value(i, is_memset);
b54d5cb9 333 for ( ; i < start + len; i++)
61b5f54d 334 buf[i] = gen_src_value(i, is_memset) | PATTERN_COPY;
e03e93a9 335 for ( ; i < buf_size; i++)
61b5f54d 336 buf[i] = gen_src_value(i, is_memset);
b54d5cb9
DW
337 buf++;
338 }
4a776f0a
HS
339}
340
e03e93a9 341static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
61b5f54d 342 unsigned int buf_size, bool is_memset)
4a776f0a
HS
343{
344 unsigned int i;
b54d5cb9
DW
345 u8 *buf;
346
347 for (; (buf = *bufs); bufs++) {
348 for (i = 0; i < start; i++)
61b5f54d 349 buf[i] = gen_dst_value(i, is_memset);
b54d5cb9 350 for ( ; i < start + len; i++)
61b5f54d
SK
351 buf[i] = gen_dst_value(i, is_memset) |
352 PATTERN_OVERWRITE;
e03e93a9 353 for ( ; i < buf_size; i++)
61b5f54d 354 buf[i] = gen_dst_value(i, is_memset);
b54d5cb9 355 }
4a776f0a
HS
356}
357
7b610178 358static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
61b5f54d 359 unsigned int counter, bool is_srcbuf, bool is_memset)
7b610178
DW
360{
361 u8 diff = actual ^ pattern;
61b5f54d 362 u8 expected = pattern | gen_inv_idx(counter, is_memset);
7b610178
DW
363 const char *thread_name = current->comm;
364
365 if (is_srcbuf)
366 pr_warn("%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n",
367 thread_name, index, expected, actual);
368 else if ((pattern & PATTERN_COPY)
369 && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
370 pr_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
371 thread_name, index, expected, actual);
372 else if (diff & PATTERN_SRC)
373 pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
374 thread_name, index, expected, actual);
375 else
376 pr_warn("%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n",
377 thread_name, index, expected, actual);
378}
379
380static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
381 unsigned int end, unsigned int counter, u8 pattern,
61b5f54d 382 bool is_srcbuf, bool is_memset)
4a776f0a
HS
383{
384 unsigned int i;
385 unsigned int error_count = 0;
386 u8 actual;
b54d5cb9
DW
387 u8 expected;
388 u8 *buf;
389 unsigned int counter_orig = counter;
390
391 for (; (buf = *bufs); bufs++) {
392 counter = counter_orig;
393 for (i = start; i < end; i++) {
394 actual = buf[i];
61b5f54d 395 expected = pattern | gen_inv_idx(counter, is_memset);
b54d5cb9 396 if (actual != expected) {
7b610178
DW
397 if (error_count < MAX_ERROR_COUNT)
398 dmatest_mismatch(actual, pattern, i,
61b5f54d
SK
399 counter, is_srcbuf,
400 is_memset);
b54d5cb9
DW
401 error_count++;
402 }
403 counter++;
4a776f0a 404 }
4a776f0a
HS
405 }
406
74b5c07a 407 if (error_count > MAX_ERROR_COUNT)
7b610178 408 pr_warn("%s: %u errors suppressed\n",
74b5c07a 409 current->comm, error_count - MAX_ERROR_COUNT);
4a776f0a
HS
410
411 return error_count;
412}
413
adfa543e
TH
414
415static void dmatest_callback(void *arg)
e44e0aa3 416{
adfa543e 417 struct dmatest_done *done = arg;
6f6a23a2 418 struct dmatest_thread *thread =
66b3bd23 419 container_of(done, struct dmatest_thread, test_done);
6f6a23a2
AW
420 if (!thread->done) {
421 done->done = true;
422 wake_up_all(done->wait);
423 } else {
424 /*
425 * If thread->done, it means that this callback occurred
426 * after the parent thread has cleaned up. This can
427 * happen in the case that driver doesn't implement
428 * the terminate_all() functionality and a dma operation
429 * did not occur within the timeout period
430 */
431 WARN(1, "dmatest: Kernel memory may be corrupted!!\n");
432 }
e44e0aa3
DW
433}
434
8be9e32b
AM
435static unsigned int min_odd(unsigned int x, unsigned int y)
436{
437 unsigned int val = min(x, y);
438
439 return val % 2 ? val : val - 1;
440}
441
872f05c6
DW
442static void result(const char *err, unsigned int n, unsigned int src_off,
443 unsigned int dst_off, unsigned int len, unsigned long data)
d86b2f29 444{
2acec150 445 pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
872f05c6 446 current->comm, n, err, src_off, dst_off, len, data);
d86b2f29
AS
447}
448
872f05c6
DW
449static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
450 unsigned int dst_off, unsigned int len,
451 unsigned long data)
95019c8c 452{
2acec150 453 pr_debug("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
a835bb85 454 current->comm, n, err, src_off, dst_off, len, data);
95019c8c
AS
455}
456
a835bb85
AS
457#define verbose_result(err, n, src_off, dst_off, len, data) ({ \
458 if (verbose) \
459 result(err, n, src_off, dst_off, len, data); \
460 else \
461 dbg_result(err, n, src_off, dst_off, len, data);\
50137a7d 462})
95019c8c 463
86727443 464static unsigned long long dmatest_persec(s64 runtime, unsigned int val)
d86b2f29 465{
86727443 466 unsigned long long per_sec = 1000000;
d86b2f29 467
86727443
DW
468 if (runtime <= 0)
469 return 0;
95019c8c 470
86727443
DW
471 /* drop precision until runtime is 32-bits */
472 while (runtime > UINT_MAX) {
473 runtime >>= 1;
474 per_sec <<= 1;
95019c8c
AS
475 }
476
86727443 477 per_sec *= val;
6138f967 478 per_sec = INT_TO_FIXPT(per_sec);
86727443 479 do_div(per_sec, runtime);
6138f967 480
86727443 481 return per_sec;
95019c8c
AS
482}
483
86727443 484static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
95019c8c 485{
6138f967 486 return FIXPT_TO_INT(dmatest_persec(runtime, len >> 10));
95019c8c
AS
487}
488
3b6679f9
AA
489static void __dmatest_free_test_data(struct dmatest_data *d, unsigned int cnt)
490{
491 unsigned int i;
492
493 for (i = 0; i < cnt; i++)
494 kfree(d->raw[i]);
495
496 kfree(d->aligned);
497 kfree(d->raw);
498}
499
500static void dmatest_free_test_data(struct dmatest_data *d)
501{
502 __dmatest_free_test_data(d, d->cnt);
503}
504
505static int dmatest_alloc_test_data(struct dmatest_data *d,
506 unsigned int buf_size, u8 align)
507{
508 unsigned int i = 0;
509
510 d->raw = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
511 if (!d->raw)
512 return -ENOMEM;
513
514 d->aligned = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
515 if (!d->aligned)
516 goto err;
517
518 for (i = 0; i < d->cnt; i++) {
519 d->raw[i] = kmalloc(buf_size + align, GFP_KERNEL);
520 if (!d->raw[i])
521 goto err;
522
523 /* align to alignment restriction */
524 if (align)
525 d->aligned[i] = PTR_ALIGN(d->raw[i], align);
526 else
527 d->aligned[i] = d->raw[i];
528 }
529
530 return 0;
531err:
532 __dmatest_free_test_data(d, i);
533 return -ENOMEM;
534}
535
4a776f0a
HS
536/*
537 * This function repeatedly tests DMA transfers of various lengths and
b54d5cb9
DW
538 * offsets for a given operation type until it is told to exit by
539 * kthread_stop(). There may be multiple threads running this function
540 * in parallel for a single channel, and there may be multiple channels
541 * being tested in parallel.
4a776f0a
HS
542 *
543 * Before each test, the source and destination buffer is initialized
544 * with a known pattern. This pattern is different depending on
545 * whether it's in an area which is supposed to be copied or
546 * overwritten, and different in the source and destination buffers.
547 * So if the DMA engine doesn't copy exactly what we tell it to copy,
548 * we'll notice.
549 */
550static int dmatest_func(void *data)
551{
552 struct dmatest_thread *thread = data;
6f6a23a2 553 struct dmatest_done *done = &thread->test_done;
e03e93a9 554 struct dmatest_info *info;
15b8a8ea 555 struct dmatest_params *params;
4a776f0a 556 struct dma_chan *chan;
8be9e32b 557 struct dma_device *dev;
4a776f0a
HS
558 unsigned int error_count;
559 unsigned int failed_tests = 0;
560 unsigned int total_tests = 0;
561 dma_cookie_t cookie;
562 enum dma_status status;
b54d5cb9 563 enum dma_ctrl_flags flags;
945b5af3 564 u8 *pq_coefs = NULL;
4a776f0a 565 int ret;
41d00bb7 566 unsigned int buf_size;
361deb72
AA
567 struct dmatest_data *src;
568 struct dmatest_data *dst;
b54d5cb9 569 int i;
e9405ef0 570 ktime_t ktime, start, diff;
8b0e1953
TG
571 ktime_t filltime = 0;
572 ktime_t comparetime = 0;
86727443
DW
573 s64 runtime = 0;
574 unsigned long long total_len = 0;
6138f967 575 unsigned long long iops = 0;
d6481608 576 u8 align = 0;
61b5f54d 577 bool is_memset = false;
72ef08bf
LA
578 dma_addr_t *srcs;
579 dma_addr_t *dma_pq;
4a776f0a 580
adfa543e 581 set_freezable();
4a776f0a
HS
582
583 ret = -ENOMEM;
4a776f0a
HS
584
585 smp_rmb();
d53513d5 586 thread->pending = false;
e03e93a9 587 info = thread->info;
15b8a8ea 588 params = &info->params;
4a776f0a 589 chan = thread->chan;
8be9e32b 590 dev = chan->device;
361deb72
AA
591 src = &thread->src;
592 dst = &thread->dst;
d6481608 593 if (thread->type == DMA_MEMCPY) {
a875abfa
SA
594 align = params->alignment < 0 ? dev->copy_align :
595 params->alignment;
361deb72 596 src->cnt = dst->cnt = 1;
61b5f54d 597 } else if (thread->type == DMA_MEMSET) {
a875abfa
SA
598 align = params->alignment < 0 ? dev->fill_align :
599 params->alignment;
361deb72 600 src->cnt = dst->cnt = 1;
61b5f54d 601 is_memset = true;
d6481608 602 } else if (thread->type == DMA_XOR) {
8be9e32b 603 /* force odd to ensure dst = src */
361deb72
AA
604 src->cnt = min_odd(params->xor_sources | 1, dev->max_xor);
605 dst->cnt = 1;
a875abfa
SA
606 align = params->alignment < 0 ? dev->xor_align :
607 params->alignment;
58691d64 608 } else if (thread->type == DMA_PQ) {
8be9e32b 609 /* force odd to ensure dst = src */
361deb72
AA
610 src->cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
611 dst->cnt = 2;
a875abfa
SA
612 align = params->alignment < 0 ? dev->pq_align :
613 params->alignment;
945b5af3 614
31d18257 615 pq_coefs = kmalloc(params->pq_sources + 1, GFP_KERNEL);
945b5af3
AS
616 if (!pq_coefs)
617 goto err_thread_type;
618
361deb72 619 for (i = 0; i < src->cnt; i++)
58691d64 620 pq_coefs[i] = 1;
b54d5cb9 621 } else
945b5af3 622 goto err_thread_type;
b54d5cb9 623
787d3083 624 /* Check if buffer count fits into map count variable (u8) */
361deb72 625 if ((src->cnt + dst->cnt) >= 255) {
787d3083 626 pr_err("too many buffers (%d of 255 supported)\n",
361deb72 627 src->cnt + dst->cnt);
3f3c7554 628 goto err_free_coefs;
787d3083
AA
629 }
630
41d00bb7
AA
631 buf_size = params->buf_size;
632 if (1 << align > buf_size) {
787d3083 633 pr_err("%u-byte buffer too small for %d-byte alignment\n",
41d00bb7 634 buf_size, 1 << align);
3f3c7554 635 goto err_free_coefs;
787d3083
AA
636 }
637
3b6679f9 638 if (dmatest_alloc_test_data(src, buf_size, align) < 0)
3f3c7554 639 goto err_free_coefs;
d6481608 640
3b6679f9
AA
641 if (dmatest_alloc_test_data(dst, buf_size, align) < 0)
642 goto err_src;
b54d5cb9 643
e44e0aa3
DW
644 set_user_nice(current, 10);
645
361deb72 646 srcs = kcalloc(src->cnt, sizeof(dma_addr_t), GFP_KERNEL);
72ef08bf 647 if (!srcs)
3b6679f9 648 goto err_dst;
72ef08bf 649
361deb72 650 dma_pq = kcalloc(dst->cnt, sizeof(dma_addr_t), GFP_KERNEL);
72ef08bf
LA
651 if (!dma_pq)
652 goto err_srcs_array;
653
b203bd3f 654 /*
d1cab34c 655 * src and dst buffers are freed by ourselves below
b203bd3f 656 */
0776ae7b 657 flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
4a776f0a 658
86727443 659 ktime = ktime_get();
0a2ff57d 660 while (!kthread_should_stop()
15b8a8ea 661 && !(params->iterations && total_tests >= params->iterations)) {
b54d5cb9 662 struct dma_async_tx_descriptor *tx = NULL;
4076e755 663 struct dmaengine_unmap_data *um;
4076e755 664 dma_addr_t *dsts;
361deb72 665 unsigned int len;
d86be86e 666
4a776f0a
HS
667 total_tests++;
668
13396a13 669 if (params->transfer_size) {
41d00bb7 670 if (params->transfer_size >= buf_size) {
13396a13 671 pr_err("%u-byte transfer size must be lower than %u-buffer size\n",
41d00bb7 672 params->transfer_size, buf_size);
13396a13
SA
673 break;
674 }
675 len = params->transfer_size;
676 } else if (params->norandom) {
41d00bb7 677 len = buf_size;
13396a13 678 } else {
41d00bb7 679 len = dmatest_random() % buf_size + 1;
13396a13 680 }
ede23a58 681
13396a13
SA
682 /* Do not alter transfer size explicitly defined by user */
683 if (!params->transfer_size) {
684 len = (len >> align) << align;
685 if (!len)
686 len = 1 << align;
687 }
ede23a58
AS
688 total_len += len;
689
2e67a087 690 if (params->norandom) {
361deb72
AA
691 src->off = 0;
692 dst->off = 0;
e3b9c347 693 } else {
41d00bb7
AA
694 src->off = dmatest_random() % (buf_size - len + 1);
695 dst->off = dmatest_random() % (buf_size - len + 1);
e3b9c347 696
361deb72
AA
697 src->off = (src->off >> align) << align;
698 dst->off = (dst->off >> align) << align;
2e67a087 699 }
e3b9c347 700
2e67a087
YS
701 if (!params->noverify) {
702 start = ktime_get();
361deb72 703 dmatest_init_srcs(src->aligned, src->off, len,
41d00bb7 704 buf_size, is_memset);
361deb72 705 dmatest_init_dsts(dst->aligned, dst->off, len,
41d00bb7 706 buf_size, is_memset);
e9405ef0
SK
707
708 diff = ktime_sub(ktime_get(), start);
709 filltime = ktime_add(filltime, diff);
e3b9c347
DW
710 }
711
361deb72 712 um = dmaengine_get_unmap_data(dev->dev, src->cnt + dst->cnt,
4076e755
DW
713 GFP_KERNEL);
714 if (!um) {
715 failed_tests++;
716 result("unmap data NULL", total_tests,
361deb72 717 src->off, dst->off, len, ret);
4076e755
DW
718 continue;
719 }
4a776f0a 720
41d00bb7 721 um->len = buf_size;
361deb72
AA
722 for (i = 0; i < src->cnt; i++) {
723 void *buf = src->aligned[i];
4076e755 724 struct page *pg = virt_to_page(buf);
f62e5f61 725 unsigned long pg_off = offset_in_page(buf);
4076e755
DW
726
727 um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
728 um->len, DMA_TO_DEVICE);
361deb72 729 srcs[i] = um->addr[i] + src->off;
4076e755 730 ret = dma_mapping_error(dev->dev, um->addr[i]);
afde3be1 731 if (ret) {
872f05c6 732 result("src mapping error", total_tests,
361deb72 733 src->off, dst->off, len, ret);
6454368a 734 goto error_unmap_continue;
afde3be1 735 }
4076e755 736 um->to_cnt++;
b54d5cb9 737 }
d86be86e 738 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
361deb72
AA
739 dsts = &um->addr[src->cnt];
740 for (i = 0; i < dst->cnt; i++) {
741 void *buf = dst->aligned[i];
4076e755 742 struct page *pg = virt_to_page(buf);
f62e5f61 743 unsigned long pg_off = offset_in_page(buf);
4076e755
DW
744
745 dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
746 DMA_BIDIRECTIONAL);
747 ret = dma_mapping_error(dev->dev, dsts[i]);
afde3be1 748 if (ret) {
872f05c6 749 result("dst mapping error", total_tests,
361deb72 750 src->off, dst->off, len, ret);
6454368a 751 goto error_unmap_continue;
afde3be1 752 }
4076e755 753 um->bidi_cnt++;
b54d5cb9
DW
754 }
755
756 if (thread->type == DMA_MEMCPY)
757 tx = dev->device_prep_dma_memcpy(chan,
361deb72 758 dsts[0] + dst->off,
4076e755 759 srcs[0], len, flags);
61b5f54d
SK
760 else if (thread->type == DMA_MEMSET)
761 tx = dev->device_prep_dma_memset(chan,
361deb72
AA
762 dsts[0] + dst->off,
763 *(src->aligned[0] + src->off),
61b5f54d 764 len, flags);
b54d5cb9
DW
765 else if (thread->type == DMA_XOR)
766 tx = dev->device_prep_dma_xor(chan,
361deb72
AA
767 dsts[0] + dst->off,
768 srcs, src->cnt,
b54d5cb9 769 len, flags);
58691d64 770 else if (thread->type == DMA_PQ) {
361deb72
AA
771 for (i = 0; i < dst->cnt; i++)
772 dma_pq[i] = dsts[i] + dst->off;
4076e755 773 tx = dev->device_prep_dma_pq(chan, dma_pq, srcs,
361deb72 774 src->cnt, pq_coefs,
58691d64
DW
775 len, flags);
776 }
d86be86e 777
d86be86e 778 if (!tx) {
361deb72
AA
779 result("prep error", total_tests, src->off,
780 dst->off, len, ret);
d86be86e 781 msleep(100);
6454368a 782 goto error_unmap_continue;
d86be86e 783 }
e44e0aa3 784
6f6a23a2 785 done->done = false;
e44e0aa3 786 tx->callback = dmatest_callback;
6f6a23a2 787 tx->callback_param = done;
d86be86e
AN
788 cookie = tx->tx_submit(tx);
789
4a776f0a 790 if (dma_submit_error(cookie)) {
361deb72
AA
791 result("submit error", total_tests, src->off,
792 dst->off, len, ret);
4a776f0a 793 msleep(100);
6454368a 794 goto error_unmap_continue;
4a776f0a 795 }
b54d5cb9 796 dma_async_issue_pending(chan);
4a776f0a 797
6f6a23a2 798 wait_event_freezable_timeout(thread->done_wait, done->done,
15b8a8ea 799 msecs_to_jiffies(params->timeout));
981ed70d 800
e44e0aa3 801 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
4a776f0a 802
6f6a23a2 803 if (!done->done) {
361deb72 804 result("test timed out", total_tests, src->off, dst->off,
872f05c6 805 len, 0);
6454368a 806 goto error_unmap_continue;
19e9f99f 807 } else if (status != DMA_COMPLETE) {
872f05c6
DW
808 result(status == DMA_ERROR ?
809 "completion error status" :
361deb72
AA
810 "completion busy status", total_tests, src->off,
811 dst->off, len, ret);
6454368a 812 goto error_unmap_continue;
4a776f0a 813 }
e44e0aa3 814
6454368a
AS
815 dmaengine_unmap_put(um);
816
e3b9c347 817 if (params->noverify) {
361deb72
AA
818 verbose_result("test passed", total_tests, src->off,
819 dst->off, len, 0);
e3b9c347
DW
820 continue;
821 }
4a776f0a 822
e9405ef0 823 start = ktime_get();
872f05c6 824 pr_debug("%s: verifying source buffer...\n", current->comm);
361deb72 825 error_count = dmatest_verify(src->aligned, 0, src->off,
61b5f54d 826 0, PATTERN_SRC, true, is_memset);
361deb72
AA
827 error_count += dmatest_verify(src->aligned, src->off,
828 src->off + len, src->off,
61b5f54d 829 PATTERN_SRC | PATTERN_COPY, true, is_memset);
361deb72 830 error_count += dmatest_verify(src->aligned, src->off + len,
41d00bb7 831 buf_size, src->off + len,
61b5f54d 832 PATTERN_SRC, true, is_memset);
7b610178 833
872f05c6 834 pr_debug("%s: verifying dest buffer...\n", current->comm);
361deb72 835 error_count += dmatest_verify(dst->aligned, 0, dst->off,
61b5f54d
SK
836 0, PATTERN_DST, false, is_memset);
837
361deb72
AA
838 error_count += dmatest_verify(dst->aligned, dst->off,
839 dst->off + len, src->off,
61b5f54d
SK
840 PATTERN_SRC | PATTERN_COPY, false, is_memset);
841
361deb72 842 error_count += dmatest_verify(dst->aligned, dst->off + len,
41d00bb7 843 buf_size, dst->off + len,
61b5f54d 844 PATTERN_DST, false, is_memset);
4a776f0a 845
e9405ef0
SK
846 diff = ktime_sub(ktime_get(), start);
847 comparetime = ktime_add(comparetime, diff);
848
4a776f0a 849 if (error_count) {
361deb72 850 result("data error", total_tests, src->off, dst->off,
872f05c6 851 len, error_count);
4a776f0a
HS
852 failed_tests++;
853 } else {
361deb72
AA
854 verbose_result("test passed", total_tests, src->off,
855 dst->off, len, 0);
4a776f0a 856 }
6454368a
AS
857
858 continue;
859
860error_unmap_continue:
861 dmaengine_unmap_put(um);
862 failed_tests++;
4a776f0a 863 }
e9405ef0
SK
864 ktime = ktime_sub(ktime_get(), ktime);
865 ktime = ktime_sub(ktime, comparetime);
866 ktime = ktime_sub(ktime, filltime);
867 runtime = ktime_to_us(ktime);
4a776f0a
HS
868
869 ret = 0;
72ef08bf
LA
870 kfree(dma_pq);
871err_srcs_array:
872 kfree(srcs);
3b6679f9
AA
873err_dst:
874 dmatest_free_test_data(dst);
875err_src:
876 dmatest_free_test_data(src);
3f3c7554 877err_free_coefs:
945b5af3
AS
878 kfree(pq_coefs);
879err_thread_type:
6138f967
SA
880 iops = dmatest_persec(runtime, total_tests);
881 pr_info("%s: summary %u tests, %u failures %llu.%02llu iops %llu KB/s (%d)\n",
86727443 882 current->comm, total_tests, failed_tests,
6138f967 883 FIXPT_TO_INT(iops), FIXPT_GET_FRAC(iops),
86727443 884 dmatest_KBs(runtime, total_len), ret);
0a2ff57d 885
9704efaa 886 /* terminate all transfers on specified channels */
6f6a23a2 887 if (ret || failed_tests)
fbffb6b4 888 dmaengine_terminate_sync(chan);
5e034f7b 889
3e5ccd86 890 thread->done = true;
2d88ce76 891 wake_up(&thread_wait);
0a2ff57d 892
4a776f0a
HS
893 return ret;
894}
895
896static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
897{
898 struct dmatest_thread *thread;
899 struct dmatest_thread *_thread;
900 int ret;
901
902 list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
903 ret = kthread_stop(thread->task);
0adff800
DW
904 pr_debug("thread %s exited with status %d\n",
905 thread->task->comm, ret);
4a776f0a 906 list_del(&thread->node);
2d88ce76 907 put_task_struct(thread->task);
4a776f0a
HS
908 kfree(thread);
909 }
9704efaa
VK
910
911 /* terminate all transfers on specified channels */
fbffb6b4 912 dmaengine_terminate_sync(dtc->chan);
9704efaa 913
4a776f0a
HS
914 kfree(dtc);
915}
916
e03e93a9
AS
917static int dmatest_add_threads(struct dmatest_info *info,
918 struct dmatest_chan *dtc, enum dma_transaction_type type)
4a776f0a 919{
15b8a8ea 920 struct dmatest_params *params = &info->params;
b54d5cb9
DW
921 struct dmatest_thread *thread;
922 struct dma_chan *chan = dtc->chan;
923 char *op;
924 unsigned int i;
4a776f0a 925
b54d5cb9
DW
926 if (type == DMA_MEMCPY)
927 op = "copy";
61b5f54d
SK
928 else if (type == DMA_MEMSET)
929 op = "set";
b54d5cb9
DW
930 else if (type == DMA_XOR)
931 op = "xor";
58691d64
DW
932 else if (type == DMA_PQ)
933 op = "pq";
b54d5cb9
DW
934 else
935 return -EINVAL;
4a776f0a 936
15b8a8ea 937 for (i = 0; i < params->threads_per_chan; i++) {
4a776f0a
HS
938 thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
939 if (!thread) {
0adff800
DW
940 pr_warn("No memory for %s-%s%u\n",
941 dma_chan_name(chan), op, i);
4a776f0a
HS
942 break;
943 }
e03e93a9 944 thread->info = info;
4a776f0a 945 thread->chan = dtc->chan;
b54d5cb9 946 thread->type = type;
6f6a23a2
AW
947 thread->test_done.wait = &thread->done_wait;
948 init_waitqueue_head(&thread->done_wait);
4a776f0a 949 smp_wmb();
2d88ce76 950 thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
b54d5cb9 951 dma_chan_name(chan), op, i);
4a776f0a 952 if (IS_ERR(thread->task)) {
2d88ce76 953 pr_warn("Failed to create thread %s-%s%u\n",
0adff800 954 dma_chan_name(chan), op, i);
4a776f0a
HS
955 kfree(thread);
956 break;
957 }
958
959 /* srcbuf and dstbuf are allocated by the thread itself */
2d88ce76 960 get_task_struct(thread->task);
4a776f0a 961 list_add_tail(&thread->node, &dtc->threads);
d53513d5 962 thread->pending = true;
4a776f0a
HS
963 }
964
b54d5cb9
DW
965 return i;
966}
967
e03e93a9
AS
968static int dmatest_add_channel(struct dmatest_info *info,
969 struct dma_chan *chan)
b54d5cb9
DW
970{
971 struct dmatest_chan *dtc;
972 struct dma_device *dma_dev = chan->device;
973 unsigned int thread_count = 0;
b9033e68 974 int cnt;
b54d5cb9
DW
975
976 dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
977 if (!dtc) {
0adff800 978 pr_warn("No memory for %s\n", dma_chan_name(chan));
b54d5cb9
DW
979 return -ENOMEM;
980 }
981
982 dtc->chan = chan;
983 INIT_LIST_HEAD(&dtc->threads);
984
985 if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
a0d4cb44
KA
986 if (dmatest == 0) {
987 cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY);
988 thread_count += cnt > 0 ? cnt : 0;
989 }
b54d5cb9 990 }
a0d4cb44 991
61b5f54d 992 if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
a0d4cb44 993 if (dmatest == 1) {
c678fa66 994 cnt = dmatest_add_threads(info, dtc, DMA_MEMSET);
a0d4cb44
KA
995 thread_count += cnt > 0 ? cnt : 0;
996 }
997 }
998
b54d5cb9 999 if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
e03e93a9 1000 cnt = dmatest_add_threads(info, dtc, DMA_XOR);
f1aef8b6 1001 thread_count += cnt > 0 ? cnt : 0;
b54d5cb9 1002 }
58691d64 1003 if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
e03e93a9 1004 cnt = dmatest_add_threads(info, dtc, DMA_PQ);
d07a74a5 1005 thread_count += cnt > 0 ? cnt : 0;
58691d64 1006 }
b54d5cb9 1007
d53513d5 1008 pr_info("Added %u threads using %s\n",
b54d5cb9 1009 thread_count, dma_chan_name(chan));
4a776f0a 1010
838cc704
AS
1011 list_add_tail(&dtc->node, &info->channels);
1012 info->nr_channels++;
4a776f0a 1013
33df8ca0 1014 return 0;
4a776f0a
HS
1015}
1016
7dd60251 1017static bool filter(struct dma_chan *chan, void *param)
4a776f0a 1018{
15b8a8ea 1019 struct dmatest_params *params = param;
e03e93a9 1020
15b8a8ea
AS
1021 if (!dmatest_match_channel(params, chan) ||
1022 !dmatest_match_device(params, chan->device))
7dd60251 1023 return false;
33df8ca0 1024 else
7dd60251 1025 return true;
4a776f0a
HS
1026}
1027
a9e55495
DW
1028static void request_channels(struct dmatest_info *info,
1029 enum dma_transaction_type type)
4a776f0a 1030{
33df8ca0 1031 dma_cap_mask_t mask;
33df8ca0
DW
1032
1033 dma_cap_zero(mask);
a9e55495 1034 dma_cap_set(type, mask);
33df8ca0 1035 for (;;) {
a9e55495
DW
1036 struct dmatest_params *params = &info->params;
1037 struct dma_chan *chan;
1038
15b8a8ea 1039 chan = dma_request_channel(mask, filter, params);
33df8ca0 1040 if (chan) {
a9e55495 1041 if (dmatest_add_channel(info, chan)) {
33df8ca0
DW
1042 dma_release_channel(chan);
1043 break; /* add_channel failed, punt */
1044 }
1045 } else
1046 break; /* no more channels available */
15b8a8ea
AS
1047 if (params->max_channels &&
1048 info->nr_channels >= params->max_channels)
33df8ca0
DW
1049 break; /* we have all we need */
1050 }
4a776f0a 1051}
4a776f0a 1052
d53513d5 1053static void add_threaded_test(struct dmatest_info *info)
851b7e16 1054{
a9e55495 1055 struct dmatest_params *params = &info->params;
851b7e16 1056
a9e55495
DW
1057 /* Copy test parameters */
1058 params->buf_size = test_buf_size;
1059 strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
1060 strlcpy(params->device, strim(test_device), sizeof(params->device));
1061 params->threads_per_chan = threads_per_chan;
1062 params->max_channels = max_channels;
1063 params->iterations = iterations;
1064 params->xor_sources = xor_sources;
1065 params->pq_sources = pq_sources;
1066 params->timeout = timeout;
e3b9c347 1067 params->noverify = noverify;
2e67a087 1068 params->norandom = norandom;
a875abfa 1069 params->alignment = alignment;
13396a13 1070 params->transfer_size = transfer_size;
a9e55495
DW
1071
1072 request_channels(info, DMA_MEMCPY);
61b5f54d 1073 request_channels(info, DMA_MEMSET);
a9e55495
DW
1074 request_channels(info, DMA_XOR);
1075 request_channels(info, DMA_PQ);
851b7e16 1076}
851b7e16 1077
d53513d5
SA
1078static void run_pending_tests(struct dmatest_info *info)
1079{
1080 struct dmatest_chan *dtc;
1081 unsigned int thread_count = 0;
1082
1083 list_for_each_entry(dtc, &info->channels, node) {
1084 struct dmatest_thread *thread;
1085
1086 thread_count = 0;
1087 list_for_each_entry(thread, &dtc->threads, node) {
1088 wake_up_process(thread->task);
1089 thread_count++;
1090 }
1091 pr_info("Started %u threads using %s\n",
1092 thread_count, dma_chan_name(dtc->chan));
1093 }
1094}
1095
a310d037 1096static void stop_threaded_test(struct dmatest_info *info)
4a776f0a 1097{
33df8ca0 1098 struct dmatest_chan *dtc, *_dtc;
7cbd4877 1099 struct dma_chan *chan;
33df8ca0 1100
838cc704 1101 list_for_each_entry_safe(dtc, _dtc, &info->channels, node) {
33df8ca0 1102 list_del(&dtc->node);
7cbd4877 1103 chan = dtc->chan;
33df8ca0 1104 dmatest_cleanup_channel(dtc);
0adff800 1105 pr_debug("dropped channel %s\n", dma_chan_name(chan));
7cbd4877 1106 dma_release_channel(chan);
33df8ca0 1107 }
838cc704
AS
1108
1109 info->nr_channels = 0;
4a776f0a 1110}
e03e93a9 1111
d53513d5 1112static void start_threaded_tests(struct dmatest_info *info)
851b7e16 1113{
a310d037
DW
1114 /* we might be called early to set run=, defer running until all
1115 * parameters have been evaluated
1116 */
1117 if (!info->did_init)
a9e55495 1118 return;
851b7e16 1119
d53513d5 1120 run_pending_tests(info);
851b7e16
AS
1121}
1122
a310d037 1123static int dmatest_run_get(char *val, const struct kernel_param *kp)
851b7e16 1124{
a310d037 1125 struct dmatest_info *info = &test_info;
851b7e16
AS
1126
1127 mutex_lock(&info->lock);
a310d037
DW
1128 if (is_threaded_test_run(info)) {
1129 dmatest_run = true;
3e5ccd86 1130 } else {
d53513d5
SA
1131 if (!is_threaded_test_pending(info))
1132 stop_threaded_test(info);
a310d037 1133 dmatest_run = false;
3e5ccd86 1134 }
851b7e16 1135 mutex_unlock(&info->lock);
851b7e16 1136
a310d037 1137 return param_get_bool(val, kp);
851b7e16
AS
1138}
1139
a310d037 1140static int dmatest_run_set(const char *val, const struct kernel_param *kp)
95019c8c 1141{
a310d037
DW
1142 struct dmatest_info *info = &test_info;
1143 int ret;
95019c8c 1144
a310d037
DW
1145 mutex_lock(&info->lock);
1146 ret = param_set_bool(val, kp);
1147 if (ret) {
851b7e16 1148 mutex_unlock(&info->lock);
a310d037 1149 return ret;
d53513d5
SA
1150 } else if (dmatest_run) {
1151 if (is_threaded_test_pending(info))
1152 start_threaded_tests(info);
1153 else
1154 pr_info("Could not start test, no channels configured\n");
1155 } else {
1156 stop_threaded_test(info);
1157 }
1158
1159 mutex_unlock(&info->lock);
1160
1161 return ret;
1162}
1163
1164static int dmatest_chan_set(const char *val, const struct kernel_param *kp)
1165{
1166 struct dmatest_info *info = &test_info;
1167 struct dmatest_chan *dtc;
1168 char chan_reset_val[20];
1169 int ret = 0;
1170
1171 mutex_lock(&info->lock);
1172 ret = param_set_copystring(val, kp);
1173 if (ret) {
1174 mutex_unlock(&info->lock);
1175 return ret;
1176 }
1177 /*Clear any previously run threads */
1178 if (!is_threaded_test_run(info) && !is_threaded_test_pending(info))
1179 stop_threaded_test(info);
1180 /* Reject channels that are already registered */
1181 if (is_threaded_test_pending(info)) {
1182 list_for_each_entry(dtc, &info->channels, node) {
1183 if (strcmp(dma_chan_name(dtc->chan),
1184 strim(test_channel)) == 0) {
1185 dtc = list_last_entry(&info->channels,
1186 struct dmatest_chan,
1187 node);
1188 strlcpy(chan_reset_val,
1189 dma_chan_name(dtc->chan),
1190 sizeof(chan_reset_val));
1191 ret = -EBUSY;
1192 goto add_chan_err;
1193 }
1194 }
95019c8c
AS
1195 }
1196
d53513d5
SA
1197 add_threaded_test(info);
1198
1199 /* Check if channel was added successfully */
1200 dtc = list_last_entry(&info->channels, struct dmatest_chan, node);
1201
1202 if (dtc->chan) {
1203 /*
1204 * if new channel was not successfully added, revert the
1205 * "test_channel" string to the name of the last successfully
1206 * added channel. exception for when users issues empty string
1207 * to channel parameter.
1208 */
1209 if ((strcmp(dma_chan_name(dtc->chan), strim(test_channel)) != 0)
1210 && (strcmp("", strim(test_channel)) != 0)) {
1211 ret = -EINVAL;
1212 strlcpy(chan_reset_val, dma_chan_name(dtc->chan),
1213 sizeof(chan_reset_val));
1214 goto add_chan_err;
1215 }
1216
1217 } else {
1218 /* Clear test_channel if no channels were added successfully */
1219 strlcpy(chan_reset_val, "", sizeof(chan_reset_val));
a310d037 1220 ret = -EBUSY;
d53513d5
SA
1221 goto add_chan_err;
1222 }
1223
1224 mutex_unlock(&info->lock);
1225
1226 return ret;
851b7e16 1227
d53513d5
SA
1228add_chan_err:
1229 param_set_copystring(chan_reset_val, kp);
a310d037 1230 mutex_unlock(&info->lock);
851b7e16 1231
a310d037 1232 return ret;
851b7e16
AS
1233}
1234
d53513d5
SA
1235static int dmatest_chan_get(char *val, const struct kernel_param *kp)
1236{
1237 struct dmatest_info *info = &test_info;
1238
1239 mutex_lock(&info->lock);
1240 if (!is_threaded_test_run(info) && !is_threaded_test_pending(info)) {
1241 stop_threaded_test(info);
1242 strlcpy(test_channel, "", sizeof(test_channel));
1243 }
1244 mutex_unlock(&info->lock);
1245
1246 return param_get_string(val, kp);
1247}
1248
1249static int dmatest_test_list_get(char *val, const struct kernel_param *kp)
1250{
1251 struct dmatest_info *info = &test_info;
1252 struct dmatest_chan *dtc;
1253 unsigned int thread_count = 0;
1254
1255 list_for_each_entry(dtc, &info->channels, node) {
1256 struct dmatest_thread *thread;
1257
1258 thread_count = 0;
1259 list_for_each_entry(thread, &dtc->threads, node) {
1260 thread_count++;
1261 }
1262 pr_info("%u threads using %s\n",
1263 thread_count, dma_chan_name(dtc->chan));
1264 }
1265
1266 return 0;
1267}
1268
e03e93a9
AS
1269static int __init dmatest_init(void)
1270{
1271 struct dmatest_info *info = &test_info;
2d88ce76 1272 struct dmatest_params *params = &info->params;
e03e93a9 1273
a310d037
DW
1274 if (dmatest_run) {
1275 mutex_lock(&info->lock);
d53513d5
SA
1276 add_threaded_test(info);
1277 run_pending_tests(info);
a310d037
DW
1278 mutex_unlock(&info->lock);
1279 }
838cc704 1280
2d88ce76
DW
1281 if (params->iterations && wait)
1282 wait_event(thread_wait, !is_threaded_test_run(info));
95019c8c 1283
a310d037
DW
1284 /* module parameters are stable, inittime tests are started,
1285 * let userspace take over 'run' control
1286 */
1287 info->did_init = true;
851b7e16 1288
851b7e16 1289 return 0;
e03e93a9
AS
1290}
1291/* when compiled-in wait for drivers to load first */
1292late_initcall(dmatest_init);
1293
1294static void __exit dmatest_exit(void)
1295{
1296 struct dmatest_info *info = &test_info;
1297
a310d037 1298 mutex_lock(&info->lock);
e03e93a9 1299 stop_threaded_test(info);
a310d037 1300 mutex_unlock(&info->lock);
e03e93a9 1301}
4a776f0a
HS
1302module_exit(dmatest_exit);
1303
e05503ef 1304MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
4a776f0a 1305MODULE_LICENSE("GPL v2");