diff options
-rw-r--r-- | Documentation/dmatest.txt | 27 | ||||
-rw-r--r-- | drivers/dma/dmatest.c | 240 |
2 files changed, 46 insertions, 221 deletions
diff --git a/Documentation/dmatest.txt b/Documentation/dmatest.txt index 8b7a5c879df9..45b8c95f1a21 100644 --- a/Documentation/dmatest.txt +++ b/Documentation/dmatest.txt | |||
@@ -16,9 +16,8 @@ be built as module or inside kernel. Let's consider those cases. | |||
16 | Part 2 - When dmatest is built as a module... | 16 | Part 2 - When dmatest is built as a module... |
17 | 17 | ||
18 | After mounting debugfs and loading the module, the /sys/kernel/debug/dmatest | 18 | After mounting debugfs and loading the module, the /sys/kernel/debug/dmatest |
19 | folder with nodes will be created. There are two important files located. First | 19 | folder with a file named 'run' nodes will be created. 'run' controls run and |
20 | is the 'run' node that controls run and stop phases of the test, and the second | 20 | stop phases of the test. |
21 | one, 'results', is used to get the test case results. | ||
22 | 21 | ||
23 | Note that in this case test will not run on load automatically. | 22 | Note that in this case test will not run on load automatically. |
24 | 23 | ||
@@ -32,8 +31,9 @@ Hint: available channel list could be extracted by running the following | |||
32 | command: | 31 | command: |
33 | % ls -1 /sys/class/dma/ | 32 | % ls -1 /sys/class/dma/ |
34 | 33 | ||
35 | After a while you will start to get messages about current status or error like | 34 | Once started a message like "dmatest: Started 1 threads using dma0chan0" is |
36 | in the original code. | 35 | emitted. After that only test failure messages are reported until the test |
36 | stops. | ||
37 | 37 | ||
38 | Note that running a new test will not stop any in progress test. | 38 | Note that running a new test will not stop any in progress test. |
39 | 39 | ||
@@ -62,19 +62,18 @@ case. You always could check them at run-time by running | |||
62 | 62 | ||
63 | Part 4 - Gathering the test results | 63 | Part 4 - Gathering the test results |
64 | 64 | ||
65 | The module provides a storage for the test results in the memory. The gathered | 65 | Test results are printed to the kernel log buffer with the format: |
66 | data could be used after test is done. | ||
67 | 66 | ||
68 | The special file 'results' in the debugfs represents gathered data of the in | 67 | "dmatest: result <channel>: <test id>: '<error msg>' with src_off=<val> dst_off=<val> len=<val> (<err code>)" |
69 | progress test. The messages collected are printed to the kernel log as well. | ||
70 | 68 | ||
71 | Example of output: | 69 | Example of output: |
72 | % cat /sys/kernel/debug/dmatest/results | 70 | % dmesg | tail -n 1 |
73 | dma0chan0-copy0: #1: No errors with src_off=0x7bf dst_off=0x8ad len=0x3fea (0) | 71 | dmatest: result dma0chan0-copy0: #1: No errors with src_off=0x7bf dst_off=0x8ad len=0x3fea (0) |
74 | 72 | ||
75 | The message format is unified across the different types of errors. A number in | 73 | The message format is unified across the different types of errors. A number in |
76 | the parens represents additional information, e.g. error code, error counter, | 74 | the parens represents additional information, e.g. error code, error counter, |
77 | or status. | 75 | or status. A test thread also emits a summary line at completion listing the |
76 | number of tests executed, number that failed, and a result code. | ||
78 | 77 | ||
79 | Note that the buffer comparison is done in the old way, i.e. data is not | 78 | The details of a data miscompare error are also emitted, but do not follow the |
80 | collected and just printed out. | 79 | above format. |
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 | ||
91 | enum 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 | |||
103 | struct 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 | |||
118 | struct dmatest_result { | ||
119 | struct list_head node; | ||
120 | char *name; | ||
121 | struct list_head results; | ||
122 | }; | ||
123 | |||
124 | struct dmatest_info; | 93 | struct dmatest_info; |
125 | 94 | ||
126 | struct dmatest_thread { | 95 | struct 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 | ||
189 | static struct dmatest_info test_info; | 154 | static 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 | ||
340 | static char *thread_result_get(const char *name, | 305 | static 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 | ||
366 | static int thread_result_add(struct dmatest_info *info, | 312 | static 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 | |||
396 | static 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 | |||
420 | static 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: | |||
731 | err_srcs: | 597 | err_srcs: |
732 | kfree(pq_coefs); | 598 | kfree(pq_coefs); |
733 | err_thread_type: | 599 | err_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 | ||
1027 | static 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 | |||
1044 | static int dtf_results_open(struct inode *inode, struct file *file) | ||
1045 | { | ||
1046 | return single_open(file, dtf_results_show, inode->i_private); | ||
1047 | } | ||
1048 | |||
1049 | static 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 | |||
1056 | static int dmatest_register_dbgfs(struct dmatest_info *info) | 890 | static 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 | ||
1078 | err_root: | 908 | err_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 | } |
1117 | module_exit(dmatest_exit); | 943 | module_exit(dmatest_exit); |
1118 | 944 | ||