aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2013-11-06 19:29:58 -0500
committerDan Williams <dan.j.williams@intel.com>2013-11-14 14:04:39 -0500
commit872f05c6e9a37e9358fd58eb54deee7337863496 (patch)
treef6afc54f45ddff8941d236550f15c0d0a96865b2 /drivers/dma
parent7b61017822cdff9c18ae70005cf52d84e8dafe5d (diff)
dmatest: replace stored results mechanism, with uniform messages
For long running tests the tracking results in a memory leak for the "ok" results, and for the failures the kernel log should be sufficient. Provide a uniform format for error messages so they can be easily parsed and remove the debugfs file. Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dmatest.c240
1 files changed, 33 insertions, 207 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index dcb38d86550e..58b195f9d03c 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -8,6 +8,8 @@
8 * 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
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
11#include <linux/delay.h> 13#include <linux/delay.h>
12#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
13#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
@@ -88,39 +90,6 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
88#define PATTERN_OVERWRITE 0x20 90#define PATTERN_OVERWRITE 0x20
89#define PATTERN_COUNT_MASK 0x1f 91#define PATTERN_COUNT_MASK 0x1f
90 92
91enum dmatest_error_type {
92 DMATEST_ET_OK,
93 DMATEST_ET_MAP_SRC,
94 DMATEST_ET_MAP_DST,
95 DMATEST_ET_PREP,
96 DMATEST_ET_SUBMIT,
97 DMATEST_ET_TIMEOUT,
98 DMATEST_ET_DMA_ERROR,
99 DMATEST_ET_DMA_IN_PROGRESS,
100 DMATEST_ET_VERIFY,
101};
102
103struct dmatest_thread_result {
104 struct list_head node;
105 unsigned int n;
106 unsigned int src_off;
107 unsigned int dst_off;
108 unsigned int len;
109 enum dmatest_error_type type;
110 union {
111 unsigned long data;
112 dma_cookie_t cookie;
113 enum dma_status status;
114 int error;
115 };
116};
117
118struct dmatest_result {
119 struct list_head node;
120 char *name;
121 struct list_head results;
122};
123
124struct dmatest_info; 93struct dmatest_info;
125 94
126struct dmatest_thread { 95struct dmatest_thread {
@@ -180,10 +149,6 @@ struct dmatest_info {
180 149
181 /* debugfs related stuff */ 150 /* debugfs related stuff */
182 struct dentry *root; 151 struct dentry *root;
183
184 /* Test results */
185 struct list_head results;
186 struct mutex results_lock;
187}; 152};
188 153
189static struct dmatest_info test_info; 154static struct dmatest_info test_info;
@@ -337,100 +302,19 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
337 return val % 2 ? val : val - 1; 302 return val % 2 ? val : val - 1;
338} 303}
339 304
340static char *thread_result_get(const char *name, 305static void result(const char *err, unsigned int n, unsigned int src_off,
341 struct dmatest_thread_result *tr) 306 unsigned int dst_off, unsigned int len, unsigned long data)
342{ 307{
343 static const char * const messages[] = { 308 pr_info("%s: result #%u: '%s' with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
344 [DMATEST_ET_OK] = "No errors", 309 current->comm, n, err, src_off, dst_off, len, data);
345 [DMATEST_ET_MAP_SRC] = "src mapping error",
346 [DMATEST_ET_MAP_DST] = "dst mapping error",
347 [DMATEST_ET_PREP] = "prep error",
348 [DMATEST_ET_SUBMIT] = "submit error",
349 [DMATEST_ET_TIMEOUT] = "test timed out",
350 [DMATEST_ET_DMA_ERROR] =
351 "got completion callback (DMA_ERROR)",
352 [DMATEST_ET_DMA_IN_PROGRESS] =
353 "got completion callback (DMA_IN_PROGRESS)",
354 [DMATEST_ET_VERIFY] = "errors",
355 };
356 static char buf[512];
357
358 snprintf(buf, sizeof(buf) - 1,
359 "%s: #%u: %s with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
360 name, tr->n, messages[tr->type], tr->src_off, tr->dst_off,
361 tr->len, tr->data);
362
363 return buf;
364} 310}
365 311
366static int thread_result_add(struct dmatest_info *info, 312static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
367 struct dmatest_result *r, enum dmatest_error_type type, 313 unsigned int dst_off, unsigned int len,
368 unsigned int n, unsigned int src_off, unsigned int dst_off, 314 unsigned long data)
369 unsigned int len, unsigned long data)
370{ 315{
371 struct dmatest_thread_result *tr; 316 pr_debug("%s: result #%u: '%s' with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
372 317 current->comm, n, err, src_off, dst_off, len, data);
373 tr = kzalloc(sizeof(*tr), GFP_KERNEL);
374 if (!tr)
375 return -ENOMEM;
376
377 tr->type = type;
378 tr->n = n;
379 tr->src_off = src_off;
380 tr->dst_off = dst_off;
381 tr->len = len;
382 tr->data = data;
383
384 mutex_lock(&info->results_lock);
385 list_add_tail(&tr->node, &r->results);
386 mutex_unlock(&info->results_lock);
387
388 if (tr->type == DMATEST_ET_OK)
389 pr_debug("%s\n", thread_result_get(r->name, tr));
390 else
391 pr_warn("%s\n", thread_result_get(r->name, tr));
392
393 return 0;
394}
395
396static void result_free(struct dmatest_info *info, const char *name)
397{
398 struct dmatest_result *r, *_r;
399
400 mutex_lock(&info->results_lock);
401 list_for_each_entry_safe(r, _r, &info->results, node) {
402 struct dmatest_thread_result *tr, *_tr;
403
404 if (name && strcmp(r->name, name))
405 continue;
406
407 list_for_each_entry_safe(tr, _tr, &r->results, node) {
408 list_del(&tr->node);
409 kfree(tr);
410 }
411
412 kfree(r->name);
413 list_del(&r->node);
414 kfree(r);
415 }
416
417 mutex_unlock(&info->results_lock);
418}
419
420static struct dmatest_result *result_init(struct dmatest_info *info,
421 const char *name)
422{
423 struct dmatest_result *r;
424
425 r = kzalloc(sizeof(*r), GFP_KERNEL);
426 if (r) {
427 r->name = kstrdup(name, GFP_KERNEL);
428 INIT_LIST_HEAD(&r->results);
429 mutex_lock(&info->results_lock);
430 list_add_tail(&r->node, &info->results);
431 mutex_unlock(&info->results_lock);
432 }
433 return r;
434} 318}
435 319
436/* 320/*
@@ -456,7 +340,6 @@ static int dmatest_func(void *data)
456 struct dmatest_params *params; 340 struct dmatest_params *params;
457 struct dma_chan *chan; 341 struct dma_chan *chan;
458 struct dma_device *dev; 342 struct dma_device *dev;
459 const char *thread_name;
460 unsigned int src_off, dst_off, len; 343 unsigned int src_off, dst_off, len;
461 unsigned int error_count; 344 unsigned int error_count;
462 unsigned int failed_tests = 0; 345 unsigned int failed_tests = 0;
@@ -469,9 +352,7 @@ static int dmatest_func(void *data)
469 int src_cnt; 352 int src_cnt;
470 int dst_cnt; 353 int dst_cnt;
471 int i; 354 int i;
472 struct dmatest_result *result;
473 355
474 thread_name = current->comm;
475 set_freezable(); 356 set_freezable();
476 357
477 ret = -ENOMEM; 358 ret = -ENOMEM;
@@ -501,10 +382,6 @@ static int dmatest_func(void *data)
501 } else 382 } else
502 goto err_thread_type; 383 goto err_thread_type;
503 384
504 result = result_init(info, thread_name);
505 if (!result)
506 goto err_srcs;
507
508 thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 385 thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
509 if (!thread->srcs) 386 if (!thread->srcs)
510 goto err_srcs; 387 goto err_srcs;
@@ -576,10 +453,8 @@ static int dmatest_func(void *data)
576 ret = dma_mapping_error(dev->dev, dma_srcs[i]); 453 ret = dma_mapping_error(dev->dev, dma_srcs[i]);
577 if (ret) { 454 if (ret) {
578 unmap_src(dev->dev, dma_srcs, len, i); 455 unmap_src(dev->dev, dma_srcs, len, i);
579 thread_result_add(info, result, 456 result("src mapping error", total_tests,
580 DMATEST_ET_MAP_SRC, 457 src_off, dst_off, len, ret);
581 total_tests, src_off, dst_off,
582 len, ret);
583 failed_tests++; 458 failed_tests++;
584 continue; 459 continue;
585 } 460 }
@@ -594,10 +469,8 @@ static int dmatest_func(void *data)
594 unmap_src(dev->dev, dma_srcs, len, src_cnt); 469 unmap_src(dev->dev, dma_srcs, len, src_cnt);
595 unmap_dst(dev->dev, dma_dsts, params->buf_size, 470 unmap_dst(dev->dev, dma_dsts, params->buf_size,
596 i); 471 i);
597 thread_result_add(info, result, 472 result("dst mapping error", total_tests,
598 DMATEST_ET_MAP_DST, 473 src_off, dst_off, len, ret);
599 total_tests, src_off, dst_off,
600 len, ret);
601 failed_tests++; 474 failed_tests++;
602 continue; 475 continue;
603 } 476 }
@@ -627,9 +500,8 @@ static int dmatest_func(void *data)
627 unmap_src(dev->dev, dma_srcs, len, src_cnt); 500 unmap_src(dev->dev, dma_srcs, len, src_cnt);
628 unmap_dst(dev->dev, dma_dsts, params->buf_size, 501 unmap_dst(dev->dev, dma_dsts, params->buf_size,
629 dst_cnt); 502 dst_cnt);
630 thread_result_add(info, result, DMATEST_ET_PREP, 503 result("prep error", total_tests, src_off,
631 total_tests, src_off, dst_off, 504 dst_off, len, ret);
632 len, 0);
633 msleep(100); 505 msleep(100);
634 failed_tests++; 506 failed_tests++;
635 continue; 507 continue;
@@ -641,9 +513,8 @@ static int dmatest_func(void *data)
641 cookie = tx->tx_submit(tx); 513 cookie = tx->tx_submit(tx);
642 514
643 if (dma_submit_error(cookie)) { 515 if (dma_submit_error(cookie)) {
644 thread_result_add(info, result, DMATEST_ET_SUBMIT, 516 result("submit error", total_tests, src_off,
645 total_tests, src_off, dst_off, 517 dst_off, len, ret);
646 len, cookie);
647 msleep(100); 518 msleep(100);
648 failed_tests++; 519 failed_tests++;
649 continue; 520 continue;
@@ -664,17 +535,15 @@ static int dmatest_func(void *data)
664 * free it this time?" dancing. For now, just 535 * free it this time?" dancing. For now, just
665 * leave it dangling. 536 * leave it dangling.
666 */ 537 */
667 thread_result_add(info, result, DMATEST_ET_TIMEOUT, 538 result("test timed out", total_tests, src_off, dst_off,
668 total_tests, src_off, dst_off, 539 len, 0);
669 len, 0);
670 failed_tests++; 540 failed_tests++;
671 continue; 541 continue;
672 } else if (status != DMA_SUCCESS) { 542 } else if (status != DMA_SUCCESS) {
673 enum dmatest_error_type type = (status == DMA_ERROR) ? 543 result(status == DMA_ERROR ?
674 DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS; 544 "completion error status" :
675 thread_result_add(info, result, type, 545 "completion busy status", total_tests, src_off,
676 total_tests, src_off, dst_off, 546 dst_off, len, ret);
677 len, status);
678 failed_tests++; 547 failed_tests++;
679 continue; 548 continue;
680 } 549 }
@@ -685,7 +554,7 @@ static int dmatest_func(void *data)
685 554
686 error_count = 0; 555 error_count = 0;
687 556
688 pr_debug("%s: verifying source buffer...\n", thread_name); 557 pr_debug("%s: verifying source buffer...\n", current->comm);
689 error_count += dmatest_verify(thread->srcs, 0, src_off, 558 error_count += dmatest_verify(thread->srcs, 0, src_off,
690 0, PATTERN_SRC, true); 559 0, PATTERN_SRC, true);
691 error_count += dmatest_verify(thread->srcs, src_off, 560 error_count += dmatest_verify(thread->srcs, src_off,
@@ -695,8 +564,7 @@ static int dmatest_func(void *data)
695 params->buf_size, src_off + len, 564 params->buf_size, src_off + len,
696 PATTERN_SRC, true); 565 PATTERN_SRC, true);
697 566
698 pr_debug("%s: verifying dest buffer...\n", 567 pr_debug("%s: verifying dest buffer...\n", current->comm);
699 thread->task->comm);
700 error_count += dmatest_verify(thread->dsts, 0, dst_off, 568 error_count += dmatest_verify(thread->dsts, 0, dst_off,
701 0, PATTERN_DST, false); 569 0, PATTERN_DST, false);
702 error_count += dmatest_verify(thread->dsts, dst_off, 570 error_count += dmatest_verify(thread->dsts, dst_off,
@@ -707,14 +575,12 @@ static int dmatest_func(void *data)
707 PATTERN_DST, false); 575 PATTERN_DST, false);
708 576
709 if (error_count) { 577 if (error_count) {
710 thread_result_add(info, result, DMATEST_ET_VERIFY, 578 result("data error", total_tests, src_off, dst_off,
711 total_tests, src_off, dst_off, 579 len, error_count);
712 len, error_count);
713 failed_tests++; 580 failed_tests++;
714 } else { 581 } else {
715 thread_result_add(info, result, DMATEST_ET_OK, 582 dbg_result("test passed", total_tests, src_off, dst_off,
716 total_tests, src_off, dst_off, 583 len, 0);
717 len, 0);
718 } 584 }
719 } 585 }
720 586
@@ -731,8 +597,8 @@ err_srcbuf:
731err_srcs: 597err_srcs:
732 kfree(pq_coefs); 598 kfree(pq_coefs);
733err_thread_type: 599err_thread_type:
734 pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 600 pr_info("%s: terminating after %u tests, %u failures (status %d)\n",
735 thread_name, total_tests, failed_tests, ret); 601 current->comm, total_tests, failed_tests, ret);
736 602
737 /* terminate all transfers on specified channels */ 603 /* terminate all transfers on specified channels */
738 if (ret) 604 if (ret)
@@ -937,9 +803,6 @@ static int __restart_threaded_test(struct dmatest_info *info, bool run)
937 if (run == false) 803 if (run == false)
938 return 0; 804 return 0;
939 805
940 /* Clear results from previous run */
941 result_free(info, NULL);
942
943 /* Copy test parameters */ 806 /* Copy test parameters */
944 params->buf_size = test_buf_size; 807 params->buf_size = test_buf_size;
945 strlcpy(params->channel, strim(test_channel), sizeof(params->channel)); 808 strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
@@ -1024,35 +887,6 @@ static const struct file_operations dtf_run_fops = {
1024 .llseek = default_llseek, 887 .llseek = default_llseek,
1025}; 888};
1026 889
1027static int dtf_results_show(struct seq_file *sf, void *data)
1028{
1029 struct dmatest_info *info = sf->private;
1030 struct dmatest_result *result;
1031 struct dmatest_thread_result *tr;
1032
1033 mutex_lock(&info->results_lock);
1034 list_for_each_entry(result, &info->results, node) {
1035 list_for_each_entry(tr, &result->results, node)
1036 seq_printf(sf, "%s\n",
1037 thread_result_get(result->name, tr));
1038 }
1039
1040 mutex_unlock(&info->results_lock);
1041 return 0;
1042}
1043
1044static int dtf_results_open(struct inode *inode, struct file *file)
1045{
1046 return single_open(file, dtf_results_show, inode->i_private);
1047}
1048
1049static const struct file_operations dtf_results_fops = {
1050 .open = dtf_results_open,
1051 .read = seq_read,
1052 .llseek = seq_lseek,
1053 .release = single_release,
1054};
1055
1056static int dmatest_register_dbgfs(struct dmatest_info *info) 890static int dmatest_register_dbgfs(struct dmatest_info *info)
1057{ 891{
1058 struct dentry *d; 892 struct dentry *d;
@@ -1069,10 +903,6 @@ static int dmatest_register_dbgfs(struct dmatest_info *info)
1069 debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, info, 903 debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, info,
1070 &dtf_run_fops); 904 &dtf_run_fops);
1071 905
1072 /* Results of test in progress */
1073 debugfs_create_file("results", S_IRUGO, info->root, info,
1074 &dtf_results_fops);
1075
1076 return 0; 906 return 0;
1077 907
1078err_root: 908err_root:
@@ -1090,9 +920,6 @@ static int __init dmatest_init(void)
1090 mutex_init(&info->lock); 920 mutex_init(&info->lock);
1091 INIT_LIST_HEAD(&info->channels); 921 INIT_LIST_HEAD(&info->channels);
1092 922
1093 mutex_init(&info->results_lock);
1094 INIT_LIST_HEAD(&info->results);
1095
1096 ret = dmatest_register_dbgfs(info); 923 ret = dmatest_register_dbgfs(info);
1097 if (ret) 924 if (ret)
1098 return ret; 925 return ret;
@@ -1112,7 +939,6 @@ static void __exit dmatest_exit(void)
1112 939
1113 debugfs_remove_recursive(info->root); 940 debugfs_remove_recursive(info->root);
1114 stop_threaded_test(info); 941 stop_threaded_test(info);
1115 result_free(info, NULL);
1116} 942}
1117module_exit(dmatest_exit); 943module_exit(dmatest_exit);
1118 944