aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/dmatest.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 12:46:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-09 12:46:45 -0400
commit1763e735b0a093a6747078b3bd101f079e576ab6 (patch)
tree75203a3229977d12dc5a5990d1122e7a3d5f30fc /drivers/dma/dmatest.c
parentb29bdba51924f6fd5971352ba111784dee3a5853 (diff)
parent3065c194670b61e213656ce25976d7c8a95e3c93 (diff)
Merge branch 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dmaengine updates from Vinod Koul: "This time we have dmatest improvements from Andy along with dw_dmac fixes. He has also done support for acpi for dmanegine. Also we have bunch of fixes going in DT support for dmanegine for various folks. Then Haswell and other ioat changes from Dave and SUDMAC support from Shimoda." * 'for-linus' of git://git.infradead.org/users/vkoul/slave-dma: (53 commits) dma: tegra: implement suspend/resume callbacks dma:of: Use a mutex to protect the of_dma_list dma: of: Fix of_node reference leak dmaengine: sirf: move driver init from module_init to subsys_initcall sudmac: add support for SUDMAC dma: sh: add Kconfig at_hdmac: move to generic DMA binding ioatdma: ioat3_alloc_sed can be static ioatdma: Adding write back descriptor error status support for ioatdma 3.3 ioatdma: S1200 platforms ioatdma channel 2 and 3 falsely advertise RAID cap ioatdma: Adding support for 16 src PQ ops and super extended descriptors ioatdma: Removing hw bug workaround for CB3.x .2 and earlier dw_dmac: add ACPI support dmaengine: call acpi_dma_request_slave_channel as well dma: acpi-dma: introduce ACPI DMA helpers dma: of: Remove unnecessary list_empty check DMA: OF: Check properties value before running be32_to_cpup() on it DMA: of: Constant names ioatdma: skip silicon bug workaround for pq_align for cb3.3 ioatdma: Removing PQ val disable for cb3.3 ...
Diffstat (limited to 'drivers/dma/dmatest.c')
-rw-r--r--drivers/dma/dmatest.c887
1 files changed, 751 insertions, 136 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index a2c8904b63ea..d8ce4ecfef18 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -2,6 +2,7 @@
2 * DMA Engine test module 2 * DMA Engine test module
3 * 3 *
4 * Copyright (C) 2007 Atmel Corporation 4 * Copyright (C) 2007 Atmel Corporation
5 * Copyright (C) 2013 Intel Corporation
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -18,6 +19,10 @@
18#include <linux/random.h> 19#include <linux/random.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
20#include <linux/wait.h> 21#include <linux/wait.h>
22#include <linux/ctype.h>
23#include <linux/debugfs.h>
24#include <linux/uaccess.h>
25#include <linux/seq_file.h>
21 26
22static unsigned int test_buf_size = 16384; 27static unsigned int test_buf_size = 16384;
23module_param(test_buf_size, uint, S_IRUGO); 28module_param(test_buf_size, uint, S_IRUGO);
@@ -61,6 +66,9 @@ module_param(timeout, uint, S_IRUGO);
61MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 66MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
62 "Pass -1 for infinite timeout"); 67 "Pass -1 for infinite timeout");
63 68
69/* Maximum amount of mismatched bytes in buffer to print */
70#define MAX_ERROR_COUNT 32
71
64/* 72/*
65 * Initialization patterns. All bytes in the source buffer has bit 7 73 * Initialization patterns. All bytes in the source buffer has bit 7
66 * set, all bytes in the destination buffer has bit 7 cleared. 74 * set, all bytes in the destination buffer has bit 7 cleared.
@@ -78,13 +86,65 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
78#define PATTERN_OVERWRITE 0x20 86#define PATTERN_OVERWRITE 0x20
79#define PATTERN_COUNT_MASK 0x1f 87#define PATTERN_COUNT_MASK 0x1f
80 88
89enum dmatest_error_type {
90 DMATEST_ET_OK,
91 DMATEST_ET_MAP_SRC,
92 DMATEST_ET_MAP_DST,
93 DMATEST_ET_PREP,
94 DMATEST_ET_SUBMIT,
95 DMATEST_ET_TIMEOUT,
96 DMATEST_ET_DMA_ERROR,
97 DMATEST_ET_DMA_IN_PROGRESS,
98 DMATEST_ET_VERIFY,
99 DMATEST_ET_VERIFY_BUF,
100};
101
102struct dmatest_verify_buffer {
103 unsigned int index;
104 u8 expected;
105 u8 actual;
106};
107
108struct dmatest_verify_result {
109 unsigned int error_count;
110 struct dmatest_verify_buffer data[MAX_ERROR_COUNT];
111 u8 pattern;
112 bool is_srcbuf;
113};
114
115struct dmatest_thread_result {
116 struct list_head node;
117 unsigned int n;
118 unsigned int src_off;
119 unsigned int dst_off;
120 unsigned int len;
121 enum dmatest_error_type type;
122 union {
123 unsigned long data;
124 dma_cookie_t cookie;
125 enum dma_status status;
126 int error;
127 struct dmatest_verify_result *vr;
128 };
129};
130
131struct dmatest_result {
132 struct list_head node;
133 char *name;
134 struct list_head results;
135};
136
137struct dmatest_info;
138
81struct dmatest_thread { 139struct dmatest_thread {
82 struct list_head node; 140 struct list_head node;
141 struct dmatest_info *info;
83 struct task_struct *task; 142 struct task_struct *task;
84 struct dma_chan *chan; 143 struct dma_chan *chan;
85 u8 **srcs; 144 u8 **srcs;
86 u8 **dsts; 145 u8 **dsts;
87 enum dma_transaction_type type; 146 enum dma_transaction_type type;
147 bool done;
88}; 148};
89 149
90struct dmatest_chan { 150struct dmatest_chan {
@@ -93,25 +153,69 @@ struct dmatest_chan {
93 struct list_head threads; 153 struct list_head threads;
94}; 154};
95 155
96/* 156/**
97 * These are protected by dma_list_mutex since they're only used by 157 * struct dmatest_params - test parameters.
98 * the DMA filter function callback 158 * @buf_size: size of the memcpy test buffer
159 * @channel: bus ID of the channel to test
160 * @device: bus ID of the DMA Engine to test
161 * @threads_per_chan: number of threads to start per channel
162 * @max_channels: maximum number of channels to use
163 * @iterations: iterations before stopping test
164 * @xor_sources: number of xor source buffers
165 * @pq_sources: number of p+q source buffers
166 * @timeout: transfer timeout in msec, -1 for infinite timeout
99 */ 167 */
100static LIST_HEAD(dmatest_channels); 168struct dmatest_params {
101static unsigned int nr_channels; 169 unsigned int buf_size;
170 char channel[20];
171 char device[20];
172 unsigned int threads_per_chan;
173 unsigned int max_channels;
174 unsigned int iterations;
175 unsigned int xor_sources;
176 unsigned int pq_sources;
177 int timeout;
178};
102 179
103static bool dmatest_match_channel(struct dma_chan *chan) 180/**
181 * struct dmatest_info - test information.
182 * @params: test parameters
183 * @lock: access protection to the fields of this structure
184 */
185struct dmatest_info {
186 /* Test parameters */
187 struct dmatest_params params;
188
189 /* Internal state */
190 struct list_head channels;
191 unsigned int nr_channels;
192 struct mutex lock;
193
194 /* debugfs related stuff */
195 struct dentry *root;
196 struct dmatest_params dbgfs_params;
197
198 /* Test results */
199 struct list_head results;
200 struct mutex results_lock;
201};
202
203static struct dmatest_info test_info;
204
205static bool dmatest_match_channel(struct dmatest_params *params,
206 struct dma_chan *chan)
104{ 207{
105 if (test_channel[0] == '\0') 208 if (params->channel[0] == '\0')
106 return true; 209 return true;
107 return strcmp(dma_chan_name(chan), test_channel) == 0; 210 return strcmp(dma_chan_name(chan), params->channel) == 0;
108} 211}
109 212
110static bool dmatest_match_device(struct dma_device *device) 213static bool dmatest_match_device(struct dmatest_params *params,
214 struct dma_device *device)
111{ 215{
112 if (test_device[0] == '\0') 216 if (params->device[0] == '\0')
113 return true; 217 return true;
114 return strcmp(dev_name(device->dev), test_device) == 0; 218 return strcmp(dev_name(device->dev), params->device) == 0;
115} 219}
116 220
117static unsigned long dmatest_random(void) 221static unsigned long dmatest_random(void)
@@ -122,7 +226,8 @@ static unsigned long dmatest_random(void)
122 return buf; 226 return buf;
123} 227}
124 228
125static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) 229static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len,
230 unsigned int buf_size)
126{ 231{
127 unsigned int i; 232 unsigned int i;
128 u8 *buf; 233 u8 *buf;
@@ -133,13 +238,14 @@ static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len)
133 for ( ; i < start + len; i++) 238 for ( ; i < start + len; i++)
134 buf[i] = PATTERN_SRC | PATTERN_COPY 239 buf[i] = PATTERN_SRC | PATTERN_COPY
135 | (~i & PATTERN_COUNT_MASK); 240 | (~i & PATTERN_COUNT_MASK);
136 for ( ; i < test_buf_size; i++) 241 for ( ; i < buf_size; i++)
137 buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 242 buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
138 buf++; 243 buf++;
139 } 244 }
140} 245}
141 246
142static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) 247static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
248 unsigned int buf_size)
143{ 249{
144 unsigned int i; 250 unsigned int i;
145 u8 *buf; 251 u8 *buf;
@@ -150,40 +256,14 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len)
150 for ( ; i < start + len; i++) 256 for ( ; i < start + len; i++)
151 buf[i] = PATTERN_DST | PATTERN_OVERWRITE 257 buf[i] = PATTERN_DST | PATTERN_OVERWRITE
152 | (~i & PATTERN_COUNT_MASK); 258 | (~i & PATTERN_COUNT_MASK);
153 for ( ; i < test_buf_size; i++) 259 for ( ; i < buf_size; i++)
154 buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 260 buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
155 } 261 }
156} 262}
157 263
158static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 264static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
159 unsigned int counter, bool is_srcbuf) 265 unsigned int start, unsigned int end, unsigned int counter,
160{ 266 u8 pattern, bool is_srcbuf)
161 u8 diff = actual ^ pattern;
162 u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
163 const char *thread_name = current->comm;
164
165 if (is_srcbuf)
166 pr_warning("%s: srcbuf[0x%x] overwritten!"
167 " Expected %02x, got %02x\n",
168 thread_name, index, expected, actual);
169 else if ((pattern & PATTERN_COPY)
170 && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
171 pr_warning("%s: dstbuf[0x%x] not copied!"
172 " Expected %02x, got %02x\n",
173 thread_name, index, expected, actual);
174 else if (diff & PATTERN_SRC)
175 pr_warning("%s: dstbuf[0x%x] was copied!"
176 " Expected %02x, got %02x\n",
177 thread_name, index, expected, actual);
178 else
179 pr_warning("%s: dstbuf[0x%x] mismatch!"
180 " Expected %02x, got %02x\n",
181 thread_name, index, expected, actual);
182}
183
184static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
185 unsigned int end, unsigned int counter, u8 pattern,
186 bool is_srcbuf)
187{ 267{
188 unsigned int i; 268 unsigned int i;
189 unsigned int error_count = 0; 269 unsigned int error_count = 0;
@@ -191,6 +271,7 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
191 u8 expected; 271 u8 expected;
192 u8 *buf; 272 u8 *buf;
193 unsigned int counter_orig = counter; 273 unsigned int counter_orig = counter;
274 struct dmatest_verify_buffer *vb;
194 275
195 for (; (buf = *bufs); bufs++) { 276 for (; (buf = *bufs); bufs++) {
196 counter = counter_orig; 277 counter = counter_orig;
@@ -198,18 +279,21 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
198 actual = buf[i]; 279 actual = buf[i];
199 expected = pattern | (~counter & PATTERN_COUNT_MASK); 280 expected = pattern | (~counter & PATTERN_COUNT_MASK);
200 if (actual != expected) { 281 if (actual != expected) {
201 if (error_count < 32) 282 if (error_count < MAX_ERROR_COUNT && vr) {
202 dmatest_mismatch(actual, pattern, i, 283 vb = &vr->data[error_count];
203 counter, is_srcbuf); 284 vb->index = i;
285 vb->expected = expected;
286 vb->actual = actual;
287 }
204 error_count++; 288 error_count++;
205 } 289 }
206 counter++; 290 counter++;
207 } 291 }
208 } 292 }
209 293
210 if (error_count > 32) 294 if (error_count > MAX_ERROR_COUNT)
211 pr_warning("%s: %u errors suppressed\n", 295 pr_warning("%s: %u errors suppressed\n",
212 current->comm, error_count - 32); 296 current->comm, error_count - MAX_ERROR_COUNT);
213 297
214 return error_count; 298 return error_count;
215} 299}
@@ -249,6 +333,170 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
249 return val % 2 ? val : val - 1; 333 return val % 2 ? val : val - 1;
250} 334}
251 335
336static char *verify_result_get_one(struct dmatest_verify_result *vr,
337 unsigned int i)
338{
339 struct dmatest_verify_buffer *vb = &vr->data[i];
340 u8 diff = vb->actual ^ vr->pattern;
341 static char buf[512];
342 char *msg;
343
344 if (vr->is_srcbuf)
345 msg = "srcbuf overwritten!";
346 else if ((vr->pattern & PATTERN_COPY)
347 && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
348 msg = "dstbuf not copied!";
349 else if (diff & PATTERN_SRC)
350 msg = "dstbuf was copied!";
351 else
352 msg = "dstbuf mismatch!";
353
354 snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
355 vb->index, vb->expected, vb->actual);
356
357 return buf;
358}
359
360static char *thread_result_get(const char *name,
361 struct dmatest_thread_result *tr)
362{
363 static const char * const messages[] = {
364 [DMATEST_ET_OK] = "No errors",
365 [DMATEST_ET_MAP_SRC] = "src mapping error",
366 [DMATEST_ET_MAP_DST] = "dst mapping error",
367 [DMATEST_ET_PREP] = "prep error",
368 [DMATEST_ET_SUBMIT] = "submit error",
369 [DMATEST_ET_TIMEOUT] = "test timed out",
370 [DMATEST_ET_DMA_ERROR] =
371 "got completion callback (DMA_ERROR)",
372 [DMATEST_ET_DMA_IN_PROGRESS] =
373 "got completion callback (DMA_IN_PROGRESS)",
374 [DMATEST_ET_VERIFY] = "errors",
375 [DMATEST_ET_VERIFY_BUF] = "verify errors",
376 };
377 static char buf[512];
378
379 snprintf(buf, sizeof(buf) - 1,
380 "%s: #%u: %s with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
381 name, tr->n, messages[tr->type], tr->src_off, tr->dst_off,
382 tr->len, tr->data);
383
384 return buf;
385}
386
387static int thread_result_add(struct dmatest_info *info,
388 struct dmatest_result *r, enum dmatest_error_type type,
389 unsigned int n, unsigned int src_off, unsigned int dst_off,
390 unsigned int len, unsigned long data)
391{
392 struct dmatest_thread_result *tr;
393
394 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
395 if (!tr)
396 return -ENOMEM;
397
398 tr->type = type;
399 tr->n = n;
400 tr->src_off = src_off;
401 tr->dst_off = dst_off;
402 tr->len = len;
403 tr->data = data;
404
405 mutex_lock(&info->results_lock);
406 list_add_tail(&tr->node, &r->results);
407 mutex_unlock(&info->results_lock);
408
409 pr_warn("%s\n", thread_result_get(r->name, tr));
410 return 0;
411}
412
413static unsigned int verify_result_add(struct dmatest_info *info,
414 struct dmatest_result *r, unsigned int n,
415 unsigned int src_off, unsigned int dst_off, unsigned int len,
416 u8 **bufs, int whence, unsigned int counter, u8 pattern,
417 bool is_srcbuf)
418{
419 struct dmatest_verify_result *vr;
420 unsigned int error_count;
421 unsigned int buf_off = is_srcbuf ? src_off : dst_off;
422 unsigned int start, end;
423
424 if (whence < 0) {
425 start = 0;
426 end = buf_off;
427 } else if (whence > 0) {
428 start = buf_off + len;
429 end = info->params.buf_size;
430 } else {
431 start = buf_off;
432 end = buf_off + len;
433 }
434
435 vr = kmalloc(sizeof(*vr), GFP_KERNEL);
436 if (!vr) {
437 pr_warn("dmatest: No memory to store verify result\n");
438 return dmatest_verify(NULL, bufs, start, end, counter, pattern,
439 is_srcbuf);
440 }
441
442 vr->pattern = pattern;
443 vr->is_srcbuf = is_srcbuf;
444
445 error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
446 is_srcbuf);
447 if (error_count) {
448 vr->error_count = error_count;
449 thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
450 dst_off, len, (unsigned long)vr);
451 return error_count;
452 }
453
454 kfree(vr);
455 return 0;
456}
457
458static void result_free(struct dmatest_info *info, const char *name)
459{
460 struct dmatest_result *r, *_r;
461
462 mutex_lock(&info->results_lock);
463 list_for_each_entry_safe(r, _r, &info->results, node) {
464 struct dmatest_thread_result *tr, *_tr;
465
466 if (name && strcmp(r->name, name))
467 continue;
468
469 list_for_each_entry_safe(tr, _tr, &r->results, node) {
470 if (tr->type == DMATEST_ET_VERIFY_BUF)
471 kfree(tr->vr);
472 list_del(&tr->node);
473 kfree(tr);
474 }
475
476 kfree(r->name);
477 list_del(&r->node);
478 kfree(r);
479 }
480
481 mutex_unlock(&info->results_lock);
482}
483
484static struct dmatest_result *result_init(struct dmatest_info *info,
485 const char *name)
486{
487 struct dmatest_result *r;
488
489 r = kzalloc(sizeof(*r), GFP_KERNEL);
490 if (r) {
491 r->name = kstrdup(name, GFP_KERNEL);
492 INIT_LIST_HEAD(&r->results);
493 mutex_lock(&info->results_lock);
494 list_add_tail(&r->node, &info->results);
495 mutex_unlock(&info->results_lock);
496 }
497 return r;
498}
499
252/* 500/*
253 * This function repeatedly tests DMA transfers of various lengths and 501 * This function repeatedly tests DMA transfers of various lengths and
254 * offsets for a given operation type until it is told to exit by 502 * offsets for a given operation type until it is told to exit by
@@ -268,6 +516,8 @@ static int dmatest_func(void *data)
268 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); 516 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait);
269 struct dmatest_thread *thread = data; 517 struct dmatest_thread *thread = data;
270 struct dmatest_done done = { .wait = &done_wait }; 518 struct dmatest_done done = { .wait = &done_wait };
519 struct dmatest_info *info;
520 struct dmatest_params *params;
271 struct dma_chan *chan; 521 struct dma_chan *chan;
272 struct dma_device *dev; 522 struct dma_device *dev;
273 const char *thread_name; 523 const char *thread_name;
@@ -278,11 +528,12 @@ static int dmatest_func(void *data)
278 dma_cookie_t cookie; 528 dma_cookie_t cookie;
279 enum dma_status status; 529 enum dma_status status;
280 enum dma_ctrl_flags flags; 530 enum dma_ctrl_flags flags;
281 u8 pq_coefs[pq_sources + 1]; 531 u8 *pq_coefs = NULL;
282 int ret; 532 int ret;
283 int src_cnt; 533 int src_cnt;
284 int dst_cnt; 534 int dst_cnt;
285 int i; 535 int i;
536 struct dmatest_result *result;
286 537
287 thread_name = current->comm; 538 thread_name = current->comm;
288 set_freezable(); 539 set_freezable();
@@ -290,28 +541,39 @@ static int dmatest_func(void *data)
290 ret = -ENOMEM; 541 ret = -ENOMEM;
291 542
292 smp_rmb(); 543 smp_rmb();
544 info = thread->info;
545 params = &info->params;
293 chan = thread->chan; 546 chan = thread->chan;
294 dev = chan->device; 547 dev = chan->device;
295 if (thread->type == DMA_MEMCPY) 548 if (thread->type == DMA_MEMCPY)
296 src_cnt = dst_cnt = 1; 549 src_cnt = dst_cnt = 1;
297 else if (thread->type == DMA_XOR) { 550 else if (thread->type == DMA_XOR) {
298 /* force odd to ensure dst = src */ 551 /* force odd to ensure dst = src */
299 src_cnt = min_odd(xor_sources | 1, dev->max_xor); 552 src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
300 dst_cnt = 1; 553 dst_cnt = 1;
301 } else if (thread->type == DMA_PQ) { 554 } else if (thread->type == DMA_PQ) {
302 /* force odd to ensure dst = src */ 555 /* force odd to ensure dst = src */
303 src_cnt = min_odd(pq_sources | 1, dma_maxpq(dev, 0)); 556 src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
304 dst_cnt = 2; 557 dst_cnt = 2;
558
559 pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
560 if (!pq_coefs)
561 goto err_thread_type;
562
305 for (i = 0; i < src_cnt; i++) 563 for (i = 0; i < src_cnt; i++)
306 pq_coefs[i] = 1; 564 pq_coefs[i] = 1;
307 } else 565 } else
566 goto err_thread_type;
567
568 result = result_init(info, thread_name);
569 if (!result)
308 goto err_srcs; 570 goto err_srcs;
309 571
310 thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 572 thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
311 if (!thread->srcs) 573 if (!thread->srcs)
312 goto err_srcs; 574 goto err_srcs;
313 for (i = 0; i < src_cnt; i++) { 575 for (i = 0; i < src_cnt; i++) {
314 thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); 576 thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
315 if (!thread->srcs[i]) 577 if (!thread->srcs[i])
316 goto err_srcbuf; 578 goto err_srcbuf;
317 } 579 }
@@ -321,7 +583,7 @@ static int dmatest_func(void *data)
321 if (!thread->dsts) 583 if (!thread->dsts)
322 goto err_dsts; 584 goto err_dsts;
323 for (i = 0; i < dst_cnt; i++) { 585 for (i = 0; i < dst_cnt; i++) {
324 thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); 586 thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
325 if (!thread->dsts[i]) 587 if (!thread->dsts[i])
326 goto err_dstbuf; 588 goto err_dstbuf;
327 } 589 }
@@ -337,7 +599,7 @@ static int dmatest_func(void *data)
337 | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; 599 | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
338 600
339 while (!kthread_should_stop() 601 while (!kthread_should_stop()
340 && !(iterations && total_tests >= iterations)) { 602 && !(params->iterations && total_tests >= params->iterations)) {
341 struct dma_async_tx_descriptor *tx = NULL; 603 struct dma_async_tx_descriptor *tx = NULL;
342 dma_addr_t dma_srcs[src_cnt]; 604 dma_addr_t dma_srcs[src_cnt];
343 dma_addr_t dma_dsts[dst_cnt]; 605 dma_addr_t dma_dsts[dst_cnt];
@@ -353,24 +615,24 @@ static int dmatest_func(void *data)
353 else if (thread->type == DMA_PQ) 615 else if (thread->type == DMA_PQ)
354 align = dev->pq_align; 616 align = dev->pq_align;
355 617
356 if (1 << align > test_buf_size) { 618 if (1 << align > params->buf_size) {
357 pr_err("%u-byte buffer too small for %d-byte alignment\n", 619 pr_err("%u-byte buffer too small for %d-byte alignment\n",
358 test_buf_size, 1 << align); 620 params->buf_size, 1 << align);
359 break; 621 break;
360 } 622 }
361 623
362 len = dmatest_random() % test_buf_size + 1; 624 len = dmatest_random() % params->buf_size + 1;
363 len = (len >> align) << align; 625 len = (len >> align) << align;
364 if (!len) 626 if (!len)
365 len = 1 << align; 627 len = 1 << align;
366 src_off = dmatest_random() % (test_buf_size - len + 1); 628 src_off = dmatest_random() % (params->buf_size - len + 1);
367 dst_off = dmatest_random() % (test_buf_size - len + 1); 629 dst_off = dmatest_random() % (params->buf_size - len + 1);
368 630
369 src_off = (src_off >> align) << align; 631 src_off = (src_off >> align) << align;
370 dst_off = (dst_off >> align) << align; 632 dst_off = (dst_off >> align) << align;
371 633
372 dmatest_init_srcs(thread->srcs, src_off, len); 634 dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size);
373 dmatest_init_dsts(thread->dsts, dst_off, len); 635 dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size);
374 636
375 for (i = 0; i < src_cnt; i++) { 637 for (i = 0; i < src_cnt; i++) {
376 u8 *buf = thread->srcs[i] + src_off; 638 u8 *buf = thread->srcs[i] + src_off;
@@ -380,10 +642,10 @@ static int dmatest_func(void *data)
380 ret = dma_mapping_error(dev->dev, dma_srcs[i]); 642 ret = dma_mapping_error(dev->dev, dma_srcs[i]);
381 if (ret) { 643 if (ret) {
382 unmap_src(dev->dev, dma_srcs, len, i); 644 unmap_src(dev->dev, dma_srcs, len, i);
383 pr_warn("%s: #%u: mapping error %d with " 645 thread_result_add(info, result,
384 "src_off=0x%x len=0x%x\n", 646 DMATEST_ET_MAP_SRC,
385 thread_name, total_tests - 1, ret, 647 total_tests, src_off, dst_off,
386 src_off, len); 648 len, ret);
387 failed_tests++; 649 failed_tests++;
388 continue; 650 continue;
389 } 651 }
@@ -391,16 +653,17 @@ static int dmatest_func(void *data)
391 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 653 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
392 for (i = 0; i < dst_cnt; i++) { 654 for (i = 0; i < dst_cnt; i++) {
393 dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 655 dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
394 test_buf_size, 656 params->buf_size,
395 DMA_BIDIRECTIONAL); 657 DMA_BIDIRECTIONAL);
396 ret = dma_mapping_error(dev->dev, dma_dsts[i]); 658 ret = dma_mapping_error(dev->dev, dma_dsts[i]);
397 if (ret) { 659 if (ret) {
398 unmap_src(dev->dev, dma_srcs, len, src_cnt); 660 unmap_src(dev->dev, dma_srcs, len, src_cnt);
399 unmap_dst(dev->dev, dma_dsts, test_buf_size, i); 661 unmap_dst(dev->dev, dma_dsts, params->buf_size,
400 pr_warn("%s: #%u: mapping error %d with " 662 i);
401 "dst_off=0x%x len=0x%x\n", 663 thread_result_add(info, result,
402 thread_name, total_tests - 1, ret, 664 DMATEST_ET_MAP_DST,
403 dst_off, test_buf_size); 665 total_tests, src_off, dst_off,
666 len, ret);
404 failed_tests++; 667 failed_tests++;
405 continue; 668 continue;
406 } 669 }
@@ -428,11 +691,11 @@ static int dmatest_func(void *data)
428 691
429 if (!tx) { 692 if (!tx) {
430 unmap_src(dev->dev, dma_srcs, len, src_cnt); 693 unmap_src(dev->dev, dma_srcs, len, src_cnt);
431 unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); 694 unmap_dst(dev->dev, dma_dsts, params->buf_size,
432 pr_warning("%s: #%u: prep error with src_off=0x%x " 695 dst_cnt);
433 "dst_off=0x%x len=0x%x\n", 696 thread_result_add(info, result, DMATEST_ET_PREP,
434 thread_name, total_tests - 1, 697 total_tests, src_off, dst_off,
435 src_off, dst_off, len); 698 len, 0);
436 msleep(100); 699 msleep(100);
437 failed_tests++; 700 failed_tests++;
438 continue; 701 continue;
@@ -444,18 +707,18 @@ static int dmatest_func(void *data)
444 cookie = tx->tx_submit(tx); 707 cookie = tx->tx_submit(tx);
445 708
446 if (dma_submit_error(cookie)) { 709 if (dma_submit_error(cookie)) {
447 pr_warning("%s: #%u: submit error %d with src_off=0x%x " 710 thread_result_add(info, result, DMATEST_ET_SUBMIT,
448 "dst_off=0x%x len=0x%x\n", 711 total_tests, src_off, dst_off,
449 thread_name, total_tests - 1, cookie, 712 len, cookie);
450 src_off, dst_off, len);
451 msleep(100); 713 msleep(100);
452 failed_tests++; 714 failed_tests++;
453 continue; 715 continue;
454 } 716 }
455 dma_async_issue_pending(chan); 717 dma_async_issue_pending(chan);
456 718
457 wait_event_freezable_timeout(done_wait, done.done, 719 wait_event_freezable_timeout(done_wait,
458 msecs_to_jiffies(timeout)); 720 done.done || kthread_should_stop(),
721 msecs_to_jiffies(params->timeout));
459 722
460 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 723 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
461 724
@@ -468,56 +731,57 @@ static int dmatest_func(void *data)
468 * free it this time?" dancing. For now, just 731 * free it this time?" dancing. For now, just
469 * leave it dangling. 732 * leave it dangling.
470 */ 733 */
471 pr_warning("%s: #%u: test timed out\n", 734 thread_result_add(info, result, DMATEST_ET_TIMEOUT,
472 thread_name, total_tests - 1); 735 total_tests, src_off, dst_off,
736 len, 0);
473 failed_tests++; 737 failed_tests++;
474 continue; 738 continue;
475 } else if (status != DMA_SUCCESS) { 739 } else if (status != DMA_SUCCESS) {
476 pr_warning("%s: #%u: got completion callback," 740 enum dmatest_error_type type = (status == DMA_ERROR) ?
477 " but status is \'%s\'\n", 741 DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS;
478 thread_name, total_tests - 1, 742 thread_result_add(info, result, type,
479 status == DMA_ERROR ? "error" : "in progress"); 743 total_tests, src_off, dst_off,
744 len, status);
480 failed_tests++; 745 failed_tests++;
481 continue; 746 continue;
482 } 747 }
483 748
484 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 749 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
485 unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); 750 unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt);
486 751
487 error_count = 0; 752 error_count = 0;
488 753
489 pr_debug("%s: verifying source buffer...\n", thread_name); 754 pr_debug("%s: verifying source buffer...\n", thread_name);
490 error_count += dmatest_verify(thread->srcs, 0, src_off, 755 error_count += verify_result_add(info, result, total_tests,
756 src_off, dst_off, len, thread->srcs, -1,
491 0, PATTERN_SRC, true); 757 0, PATTERN_SRC, true);
492 error_count += dmatest_verify(thread->srcs, src_off, 758 error_count += verify_result_add(info, result, total_tests,
493 src_off + len, src_off, 759 src_off, dst_off, len, thread->srcs, 0,
494 PATTERN_SRC | PATTERN_COPY, true); 760 src_off, PATTERN_SRC | PATTERN_COPY, true);
495 error_count += dmatest_verify(thread->srcs, src_off + len, 761 error_count += verify_result_add(info, result, total_tests,
496 test_buf_size, src_off + len, 762 src_off, dst_off, len, thread->srcs, 1,
497 PATTERN_SRC, true); 763 src_off + len, PATTERN_SRC, true);
498 764
499 pr_debug("%s: verifying dest buffer...\n", 765 pr_debug("%s: verifying dest buffer...\n", thread_name);
500 thread->task->comm); 766 error_count += verify_result_add(info, result, total_tests,
501 error_count += dmatest_verify(thread->dsts, 0, dst_off, 767 src_off, dst_off, len, thread->dsts, -1,
502 0, PATTERN_DST, false); 768 0, PATTERN_DST, false);
503 error_count += dmatest_verify(thread->dsts, dst_off, 769 error_count += verify_result_add(info, result, total_tests,
504 dst_off + len, src_off, 770 src_off, dst_off, len, thread->dsts, 0,
505 PATTERN_SRC | PATTERN_COPY, false); 771 src_off, PATTERN_SRC | PATTERN_COPY, false);
506 error_count += dmatest_verify(thread->dsts, dst_off + len, 772 error_count += verify_result_add(info, result, total_tests,
507 test_buf_size, dst_off + len, 773 src_off, dst_off, len, thread->dsts, 1,
508 PATTERN_DST, false); 774 dst_off + len, PATTERN_DST, false);
509 775
510 if (error_count) { 776 if (error_count) {
511 pr_warning("%s: #%u: %u errors with " 777 thread_result_add(info, result, DMATEST_ET_VERIFY,
512 "src_off=0x%x dst_off=0x%x len=0x%x\n", 778 total_tests, src_off, dst_off,
513 thread_name, total_tests - 1, error_count, 779 len, error_count);
514 src_off, dst_off, len);
515 failed_tests++; 780 failed_tests++;
516 } else { 781 } else {
517 pr_debug("%s: #%u: No errors with " 782 thread_result_add(info, result, DMATEST_ET_OK,
518 "src_off=0x%x dst_off=0x%x len=0x%x\n", 783 total_tests, src_off, dst_off,
519 thread_name, total_tests - 1, 784 len, 0);
520 src_off, dst_off, len);
521 } 785 }
522 } 786 }
523 787
@@ -532,6 +796,8 @@ err_dsts:
532err_srcbuf: 796err_srcbuf:
533 kfree(thread->srcs); 797 kfree(thread->srcs);
534err_srcs: 798err_srcs:
799 kfree(pq_coefs);
800err_thread_type:
535 pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 801 pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
536 thread_name, total_tests, failed_tests, ret); 802 thread_name, total_tests, failed_tests, ret);
537 803
@@ -539,7 +805,9 @@ err_srcs:
539 if (ret) 805 if (ret)
540 dmaengine_terminate_all(chan); 806 dmaengine_terminate_all(chan);
541 807
542 if (iterations > 0) 808 thread->done = true;
809
810 if (params->iterations > 0)
543 while (!kthread_should_stop()) { 811 while (!kthread_should_stop()) {
544 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 812 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
545 interruptible_sleep_on(&wait_dmatest_exit); 813 interruptible_sleep_on(&wait_dmatest_exit);
@@ -568,8 +836,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
568 kfree(dtc); 836 kfree(dtc);
569} 837}
570 838
571static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_type type) 839static int dmatest_add_threads(struct dmatest_info *info,
840 struct dmatest_chan *dtc, enum dma_transaction_type type)
572{ 841{
842 struct dmatest_params *params = &info->params;
573 struct dmatest_thread *thread; 843 struct dmatest_thread *thread;
574 struct dma_chan *chan = dtc->chan; 844 struct dma_chan *chan = dtc->chan;
575 char *op; 845 char *op;
@@ -584,7 +854,7 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
584 else 854 else
585 return -EINVAL; 855 return -EINVAL;
586 856
587 for (i = 0; i < threads_per_chan; i++) { 857 for (i = 0; i < params->threads_per_chan; i++) {
588 thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 858 thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
589 if (!thread) { 859 if (!thread) {
590 pr_warning("dmatest: No memory for %s-%s%u\n", 860 pr_warning("dmatest: No memory for %s-%s%u\n",
@@ -592,6 +862,7 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
592 862
593 break; 863 break;
594 } 864 }
865 thread->info = info;
595 thread->chan = dtc->chan; 866 thread->chan = dtc->chan;
596 thread->type = type; 867 thread->type = type;
597 smp_wmb(); 868 smp_wmb();
@@ -612,7 +883,8 @@ static int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_ty
612 return i; 883 return i;
613} 884}
614 885
615static int dmatest_add_channel(struct dma_chan *chan) 886static int dmatest_add_channel(struct dmatest_info *info,
887 struct dma_chan *chan)
616{ 888{
617 struct dmatest_chan *dtc; 889 struct dmatest_chan *dtc;
618 struct dma_device *dma_dev = chan->device; 890 struct dma_device *dma_dev = chan->device;
@@ -629,75 +901,418 @@ static int dmatest_add_channel(struct dma_chan *chan)
629 INIT_LIST_HEAD(&dtc->threads); 901 INIT_LIST_HEAD(&dtc->threads);
630 902
631 if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 903 if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
632 cnt = dmatest_add_threads(dtc, DMA_MEMCPY); 904 cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY);
633 thread_count += cnt > 0 ? cnt : 0; 905 thread_count += cnt > 0 ? cnt : 0;
634 } 906 }
635 if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 907 if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
636 cnt = dmatest_add_threads(dtc, DMA_XOR); 908 cnt = dmatest_add_threads(info, dtc, DMA_XOR);
637 thread_count += cnt > 0 ? cnt : 0; 909 thread_count += cnt > 0 ? cnt : 0;
638 } 910 }
639 if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 911 if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
640 cnt = dmatest_add_threads(dtc, DMA_PQ); 912 cnt = dmatest_add_threads(info, dtc, DMA_PQ);
641 thread_count += cnt > 0 ? cnt : 0; 913 thread_count += cnt > 0 ? cnt : 0;
642 } 914 }
643 915
644 pr_info("dmatest: Started %u threads using %s\n", 916 pr_info("dmatest: Started %u threads using %s\n",
645 thread_count, dma_chan_name(chan)); 917 thread_count, dma_chan_name(chan));
646 918
647 list_add_tail(&dtc->node, &dmatest_channels); 919 list_add_tail(&dtc->node, &info->channels);
648 nr_channels++; 920 info->nr_channels++;
649 921
650 return 0; 922 return 0;
651} 923}
652 924
653static bool filter(struct dma_chan *chan, void *param) 925static bool filter(struct dma_chan *chan, void *param)
654{ 926{
655 if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device)) 927 struct dmatest_params *params = param;
928
929 if (!dmatest_match_channel(params, chan) ||
930 !dmatest_match_device(params, chan->device))
656 return false; 931 return false;
657 else 932 else
658 return true; 933 return true;
659} 934}
660 935
661static int __init dmatest_init(void) 936static int __run_threaded_test(struct dmatest_info *info)
662{ 937{
663 dma_cap_mask_t mask; 938 dma_cap_mask_t mask;
664 struct dma_chan *chan; 939 struct dma_chan *chan;
940 struct dmatest_params *params = &info->params;
665 int err = 0; 941 int err = 0;
666 942
667 dma_cap_zero(mask); 943 dma_cap_zero(mask);
668 dma_cap_set(DMA_MEMCPY, mask); 944 dma_cap_set(DMA_MEMCPY, mask);
669 for (;;) { 945 for (;;) {
670 chan = dma_request_channel(mask, filter, NULL); 946 chan = dma_request_channel(mask, filter, params);
671 if (chan) { 947 if (chan) {
672 err = dmatest_add_channel(chan); 948 err = dmatest_add_channel(info, chan);
673 if (err) { 949 if (err) {
674 dma_release_channel(chan); 950 dma_release_channel(chan);
675 break; /* add_channel failed, punt */ 951 break; /* add_channel failed, punt */
676 } 952 }
677 } else 953 } else
678 break; /* no more channels available */ 954 break; /* no more channels available */
679 if (max_channels && nr_channels >= max_channels) 955 if (params->max_channels &&
956 info->nr_channels >= params->max_channels)
680 break; /* we have all we need */ 957 break; /* we have all we need */
681 } 958 }
682
683 return err; 959 return err;
684} 960}
685/* when compiled-in wait for drivers to load first */
686late_initcall(dmatest_init);
687 961
688static void __exit dmatest_exit(void) 962#ifndef MODULE
963static int run_threaded_test(struct dmatest_info *info)
964{
965 int ret;
966
967 mutex_lock(&info->lock);
968 ret = __run_threaded_test(info);
969 mutex_unlock(&info->lock);
970 return ret;
971}
972#endif
973
974static void __stop_threaded_test(struct dmatest_info *info)
689{ 975{
690 struct dmatest_chan *dtc, *_dtc; 976 struct dmatest_chan *dtc, *_dtc;
691 struct dma_chan *chan; 977 struct dma_chan *chan;
692 978
693 list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { 979 list_for_each_entry_safe(dtc, _dtc, &info->channels, node) {
694 list_del(&dtc->node); 980 list_del(&dtc->node);
695 chan = dtc->chan; 981 chan = dtc->chan;
696 dmatest_cleanup_channel(dtc); 982 dmatest_cleanup_channel(dtc);
697 pr_debug("dmatest: dropped channel %s\n", 983 pr_debug("dmatest: dropped channel %s\n", dma_chan_name(chan));
698 dma_chan_name(chan));
699 dma_release_channel(chan); 984 dma_release_channel(chan);
700 } 985 }
986
987 info->nr_channels = 0;
988}
989
990static void stop_threaded_test(struct dmatest_info *info)
991{
992 mutex_lock(&info->lock);
993 __stop_threaded_test(info);
994 mutex_unlock(&info->lock);
995}
996
997static int __restart_threaded_test(struct dmatest_info *info, bool run)
998{
999 struct dmatest_params *params = &info->params;
1000 int ret;
1001
1002 /* Stop any running test first */
1003 __stop_threaded_test(info);
1004
1005 if (run == false)
1006 return 0;
1007
1008 /* Clear results from previous run */
1009 result_free(info, NULL);
1010
1011 /* Copy test parameters */
1012 memcpy(params, &info->dbgfs_params, sizeof(*params));
1013
1014 /* Run test with new parameters */
1015 ret = __run_threaded_test(info);
1016 if (ret) {
1017 __stop_threaded_test(info);
1018 pr_err("dmatest: Can't run test\n");
1019 }
1020
1021 return ret;
1022}
1023
1024static ssize_t dtf_write_string(void *to, size_t available, loff_t *ppos,
1025 const void __user *from, size_t count)
1026{
1027 char tmp[20];
1028 ssize_t len;
1029
1030 len = simple_write_to_buffer(tmp, sizeof(tmp) - 1, ppos, from, count);
1031 if (len >= 0) {
1032 tmp[len] = '\0';
1033 strlcpy(to, strim(tmp), available);
1034 }
1035
1036 return len;
1037}
1038
1039static ssize_t dtf_read_channel(struct file *file, char __user *buf,
1040 size_t count, loff_t *ppos)
1041{
1042 struct dmatest_info *info = file->private_data;
1043 return simple_read_from_buffer(buf, count, ppos,
1044 info->dbgfs_params.channel,
1045 strlen(info->dbgfs_params.channel));
1046}
1047
1048static ssize_t dtf_write_channel(struct file *file, const char __user *buf,
1049 size_t size, loff_t *ppos)
1050{
1051 struct dmatest_info *info = file->private_data;
1052 return dtf_write_string(info->dbgfs_params.channel,
1053 sizeof(info->dbgfs_params.channel),
1054 ppos, buf, size);
1055}
1056
1057static const struct file_operations dtf_channel_fops = {
1058 .read = dtf_read_channel,
1059 .write = dtf_write_channel,
1060 .open = simple_open,
1061 .llseek = default_llseek,
1062};
1063
1064static ssize_t dtf_read_device(struct file *file, char __user *buf,
1065 size_t count, loff_t *ppos)
1066{
1067 struct dmatest_info *info = file->private_data;
1068 return simple_read_from_buffer(buf, count, ppos,
1069 info->dbgfs_params.device,
1070 strlen(info->dbgfs_params.device));
1071}
1072
1073static ssize_t dtf_write_device(struct file *file, const char __user *buf,
1074 size_t size, loff_t *ppos)
1075{
1076 struct dmatest_info *info = file->private_data;
1077 return dtf_write_string(info->dbgfs_params.device,
1078 sizeof(info->dbgfs_params.device),
1079 ppos, buf, size);
1080}
1081
1082static const struct file_operations dtf_device_fops = {
1083 .read = dtf_read_device,
1084 .write = dtf_write_device,
1085 .open = simple_open,
1086 .llseek = default_llseek,
1087};
1088
1089static ssize_t dtf_read_run(struct file *file, char __user *user_buf,
1090 size_t count, loff_t *ppos)
1091{
1092 struct dmatest_info *info = file->private_data;
1093 char buf[3];
1094 struct dmatest_chan *dtc;
1095 bool alive = false;
1096
1097 mutex_lock(&info->lock);
1098 list_for_each_entry(dtc, &info->channels, node) {
1099 struct dmatest_thread *thread;
1100
1101 list_for_each_entry(thread, &dtc->threads, node) {
1102 if (!thread->done) {
1103 alive = true;
1104 break;
1105 }
1106 }
1107 }
1108
1109 if (alive) {
1110 buf[0] = 'Y';
1111 } else {
1112 __stop_threaded_test(info);
1113 buf[0] = 'N';
1114 }
1115
1116 mutex_unlock(&info->lock);
1117 buf[1] = '\n';
1118 buf[2] = 0x00;
1119 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
1120}
1121
1122static ssize_t dtf_write_run(struct file *file, const char __user *user_buf,
1123 size_t count, loff_t *ppos)
1124{
1125 struct dmatest_info *info = file->private_data;
1126 char buf[16];
1127 bool bv;
1128 int ret = 0;
1129
1130 if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1))))
1131 return -EFAULT;
1132
1133 if (strtobool(buf, &bv) == 0) {
1134 mutex_lock(&info->lock);
1135 ret = __restart_threaded_test(info, bv);
1136 mutex_unlock(&info->lock);
1137 }
1138
1139 return ret ? ret : count;
1140}
1141
1142static const struct file_operations dtf_run_fops = {
1143 .read = dtf_read_run,
1144 .write = dtf_write_run,
1145 .open = simple_open,
1146 .llseek = default_llseek,
1147};
1148
1149static int dtf_results_show(struct seq_file *sf, void *data)
1150{
1151 struct dmatest_info *info = sf->private;
1152 struct dmatest_result *result;
1153 struct dmatest_thread_result *tr;
1154 unsigned int i;
1155
1156 mutex_lock(&info->results_lock);
1157 list_for_each_entry(result, &info->results, node) {
1158 list_for_each_entry(tr, &result->results, node) {
1159 seq_printf(sf, "%s\n",
1160 thread_result_get(result->name, tr));
1161 if (tr->type == DMATEST_ET_VERIFY_BUF) {
1162 for (i = 0; i < tr->vr->error_count; i++) {
1163 seq_printf(sf, "\t%s\n",
1164 verify_result_get_one(tr->vr, i));
1165 }
1166 }
1167 }
1168 }
1169
1170 mutex_unlock(&info->results_lock);
1171 return 0;
1172}
1173
1174static int dtf_results_open(struct inode *inode, struct file *file)
1175{
1176 return single_open(file, dtf_results_show, inode->i_private);
1177}
1178
1179static const struct file_operations dtf_results_fops = {
1180 .open = dtf_results_open,
1181 .read = seq_read,
1182 .llseek = seq_lseek,
1183 .release = single_release,
1184};
1185
1186static int dmatest_register_dbgfs(struct dmatest_info *info)
1187{
1188 struct dentry *d;
1189 struct dmatest_params *params = &info->dbgfs_params;
1190 int ret = -ENOMEM;
1191
1192 d = debugfs_create_dir("dmatest", NULL);
1193 if (IS_ERR(d))
1194 return PTR_ERR(d);
1195 if (!d)
1196 goto err_root;
1197
1198 info->root = d;
1199
1200 /* Copy initial values */
1201 memcpy(params, &info->params, sizeof(*params));
1202
1203 /* Test parameters */
1204
1205 d = debugfs_create_u32("test_buf_size", S_IWUSR | S_IRUGO, info->root,
1206 (u32 *)&params->buf_size);
1207 if (IS_ERR_OR_NULL(d))
1208 goto err_node;
1209
1210 d = debugfs_create_file("channel", S_IRUGO | S_IWUSR, info->root,
1211 info, &dtf_channel_fops);
1212 if (IS_ERR_OR_NULL(d))
1213 goto err_node;
1214
1215 d = debugfs_create_file("device", S_IRUGO | S_IWUSR, info->root,
1216 info, &dtf_device_fops);
1217 if (IS_ERR_OR_NULL(d))
1218 goto err_node;
1219
1220 d = debugfs_create_u32("threads_per_chan", S_IWUSR | S_IRUGO, info->root,
1221 (u32 *)&params->threads_per_chan);
1222 if (IS_ERR_OR_NULL(d))
1223 goto err_node;
1224
1225 d = debugfs_create_u32("max_channels", S_IWUSR | S_IRUGO, info->root,
1226 (u32 *)&params->max_channels);
1227 if (IS_ERR_OR_NULL(d))
1228 goto err_node;
1229
1230 d = debugfs_create_u32("iterations", S_IWUSR | S_IRUGO, info->root,
1231 (u32 *)&params->iterations);
1232 if (IS_ERR_OR_NULL(d))
1233 goto err_node;
1234
1235 d = debugfs_create_u32("xor_sources", S_IWUSR | S_IRUGO, info->root,
1236 (u32 *)&params->xor_sources);
1237 if (IS_ERR_OR_NULL(d))
1238 goto err_node;
1239
1240 d = debugfs_create_u32("pq_sources", S_IWUSR | S_IRUGO, info->root,
1241 (u32 *)&params->pq_sources);
1242 if (IS_ERR_OR_NULL(d))
1243 goto err_node;
1244
1245 d = debugfs_create_u32("timeout", S_IWUSR | S_IRUGO, info->root,
1246 (u32 *)&params->timeout);
1247 if (IS_ERR_OR_NULL(d))
1248 goto err_node;
1249
1250 /* Run or stop threaded test */
1251 d = debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root,
1252 info, &dtf_run_fops);
1253 if (IS_ERR_OR_NULL(d))
1254 goto err_node;
1255
1256 /* Results of test in progress */
1257 d = debugfs_create_file("results", S_IRUGO, info->root, info,
1258 &dtf_results_fops);
1259 if (IS_ERR_OR_NULL(d))
1260 goto err_node;
1261
1262 return 0;
1263
1264err_node:
1265 debugfs_remove_recursive(info->root);
1266err_root:
1267 pr_err("dmatest: Failed to initialize debugfs\n");
1268 return ret;
1269}
1270
1271static int __init dmatest_init(void)
1272{
1273 struct dmatest_info *info = &test_info;
1274 struct dmatest_params *params = &info->params;
1275 int ret;
1276
1277 memset(info, 0, sizeof(*info));
1278
1279 mutex_init(&info->lock);
1280 INIT_LIST_HEAD(&info->channels);
1281
1282 mutex_init(&info->results_lock);
1283 INIT_LIST_HEAD(&info->results);
1284
1285 /* Set default parameters */
1286 params->buf_size = test_buf_size;
1287 strlcpy(params->channel, test_channel, sizeof(params->channel));
1288 strlcpy(params->device, test_device, sizeof(params->device));
1289 params->threads_per_chan = threads_per_chan;
1290 params->max_channels = max_channels;
1291 params->iterations = iterations;
1292 params->xor_sources = xor_sources;
1293 params->pq_sources = pq_sources;
1294 params->timeout = timeout;
1295
1296 ret = dmatest_register_dbgfs(info);
1297 if (ret)
1298 return ret;
1299
1300#ifdef MODULE
1301 return 0;
1302#else
1303 return run_threaded_test(info);
1304#endif
1305}
1306/* when compiled-in wait for drivers to load first */
1307late_initcall(dmatest_init);
1308
1309static void __exit dmatest_exit(void)
1310{
1311 struct dmatest_info *info = &test_info;
1312
1313 debugfs_remove_recursive(info->root);
1314 stop_threaded_test(info);
1315 result_free(info, NULL);
701} 1316}
702module_exit(dmatest_exit); 1317module_exit(dmatest_exit);
703 1318