aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2013-11-06 19:30:01 -0500
committerDan Williams <dan.j.williams@intel.com>2013-11-14 14:04:39 -0500
commita310d037b8d06755c62bb4878c00d19490af5550 (patch)
tree7546e7c90f51bb2491558ce4772740ad9e903540
parent0adff800662f52d0ffc3e420db231769cb3fff13 (diff)
dmatest: restore ability to start test at module load and init
1/ move 'run' control to a module parameter so we can do: modprobe dmatest run=1. With this moved the rest of the debugfs boilerplate can go. 2/ Fix parameter initialization. Previously the test was being started without taking the parameters into account in the built-in case. Also killed off the '__' version of some routines. The new rule is just hold the lock when calling a *threaded_test() routine. Acked-by: Linus Walleij <linus.walleij@linaro.org> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--Documentation/dmatest.txt18
-rw-r--r--drivers/dma/dmatest.c265
2 files changed, 116 insertions, 167 deletions
diff --git a/Documentation/dmatest.txt b/Documentation/dmatest.txt
index 45b8c95f1a21..e6e16a7f3706 100644
--- a/Documentation/dmatest.txt
+++ b/Documentation/dmatest.txt
@@ -15,17 +15,19 @@ be built as module or inside kernel. Let's consider those cases.
15 15
16 Part 2 - When dmatest is built as a module... 16 Part 2 - When dmatest is built as a module...
17 17
18After mounting debugfs and loading the module, the /sys/kernel/debug/dmatest
19folder with a file named 'run' nodes will be created. 'run' controls run and
20stop phases of the test.
21
22Note that in this case test will not run on load automatically.
23
24Example of usage: 18Example of usage:
19 % modprobe dmatest channel=dma0chan0 timeout=2000 iterations=1 run=1
20
21...or:
22 % modprobe dmatest
25 % echo dma0chan0 > /sys/module/dmatest/parameters/channel 23 % echo dma0chan0 > /sys/module/dmatest/parameters/channel
26 % echo 2000 > /sys/module/dmatest/parameters/timeout 24 % echo 2000 > /sys/module/dmatest/parameters/timeout
27 % echo 1 > /sys/module/dmatest/parameters/iterations 25 % echo 1 > /sys/module/dmatest/parameters/iterations
28 % echo 1 > /sys/kernel/debug/dmatest/run 26 % echo 1 > /sys/module/dmatest/parameters/run
27
28...or on the kernel command line:
29
30 dmatest.channel=dma0chan0 dmatest.timeout=2000 dmatest.iterations=1 dmatest.run=1
29 31
30Hint: available channel list could be extracted by running the following 32Hint: available channel list could be extracted by running the following
31command: 33command:
@@ -42,7 +44,7 @@ The following command should return actual state of the test.
42 44
43To wait for test done the user may perform a busy loop that checks the state. 45To wait for test done the user may perform a busy loop that checks the state.
44 46
45 % while [ $(cat /sys/kernel/debug/dmatest/run) = "Y" ] 47 % while [ $(cat /sys/module/dmatest/parameters/run) = "Y" ]
46 > do 48 > do
47 > echo -n "." 49 > echo -n "."
48 > sleep 1 50 > sleep 1
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 15199edcc366..c5048671daf7 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -21,10 +21,6 @@
21#include <linux/random.h> 21#include <linux/random.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/wait.h> 23#include <linux/wait.h>
24#include <linux/ctype.h>
25#include <linux/debugfs.h>
26#include <linux/uaccess.h>
27#include <linux/seq_file.h>
28 24
29static unsigned int test_buf_size = 16384; 25static unsigned int test_buf_size = 16384;
30module_param(test_buf_size, uint, S_IRUGO | S_IWUSR); 26module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
@@ -70,45 +66,6 @@ module_param(timeout, uint, S_IRUGO | S_IWUSR);
70MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 66MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
71 "Pass -1 for infinite timeout"); 67 "Pass -1 for infinite timeout");
72 68
73/* Maximum amount of mismatched bytes in buffer to print */
74#define MAX_ERROR_COUNT 32
75
76/*
77 * Initialization patterns. All bytes in the source buffer has bit 7
78 * set, all bytes in the destination buffer has bit 7 cleared.
79 *
80 * Bit 6 is set for all bytes which are to be copied by the DMA
81 * engine. Bit 5 is set for all bytes which are to be overwritten by
82 * the DMA engine.
83 *
84 * The remaining bits are the inverse of a counter which increments by
85 * one for each byte address.
86 */
87#define PATTERN_SRC 0x80
88#define PATTERN_DST 0x00
89#define PATTERN_COPY 0x40
90#define PATTERN_OVERWRITE 0x20
91#define PATTERN_COUNT_MASK 0x1f
92
93struct dmatest_info;
94
95struct dmatest_thread {
96 struct list_head node;
97 struct dmatest_info *info;
98 struct task_struct *task;
99 struct dma_chan *chan;
100 u8 **srcs;
101 u8 **dsts;
102 enum dma_transaction_type type;
103 bool done;
104};
105
106struct dmatest_chan {
107 struct list_head node;
108 struct dma_chan *chan;
109 struct list_head threads;
110};
111
112/** 69/**
113 * struct dmatest_params - test parameters. 70 * struct dmatest_params - test parameters.
114 * @buf_size: size of the memcpy test buffer 71 * @buf_size: size of the memcpy test buffer
@@ -138,7 +95,7 @@ struct dmatest_params {
138 * @params: test parameters 95 * @params: test parameters
139 * @lock: access protection to the fields of this structure 96 * @lock: access protection to the fields of this structure
140 */ 97 */
141struct dmatest_info { 98static struct dmatest_info {
142 /* Test parameters */ 99 /* Test parameters */
143 struct dmatest_params params; 100 struct dmatest_params params;
144 101
@@ -146,12 +103,58 @@ struct dmatest_info {
146 struct list_head channels; 103 struct list_head channels;
147 unsigned int nr_channels; 104 unsigned int nr_channels;
148 struct mutex lock; 105 struct mutex lock;
106 bool did_init;
107} test_info = {
108 .channels = LIST_HEAD_INIT(test_info.channels),
109 .lock = __MUTEX_INITIALIZER(test_info.lock),
110};
149 111
150 /* debugfs related stuff */ 112static int dmatest_run_set(const char *val, const struct kernel_param *kp);
151 struct dentry *root; 113static int dmatest_run_get(char *val, const struct kernel_param *kp);
114static struct kernel_param_ops run_ops = {
115 .set = dmatest_run_set,
116 .get = dmatest_run_get,
152}; 117};
118static bool dmatest_run;
119module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR);
120MODULE_PARM_DESC(run, "Run the test (default: false)");
153 121
154static struct dmatest_info test_info; 122/* Maximum amount of mismatched bytes in buffer to print */
123#define MAX_ERROR_COUNT 32
124
125/*
126 * Initialization patterns. All bytes in the source buffer has bit 7
127 * set, all bytes in the destination buffer has bit 7 cleared.
128 *
129 * Bit 6 is set for all bytes which are to be copied by the DMA
130 * engine. Bit 5 is set for all bytes which are to be overwritten by
131 * the DMA engine.
132 *
133 * The remaining bits are the inverse of a counter which increments by
134 * one for each byte address.
135 */
136#define PATTERN_SRC 0x80
137#define PATTERN_DST 0x00
138#define PATTERN_COPY 0x40
139#define PATTERN_OVERWRITE 0x20
140#define PATTERN_COUNT_MASK 0x1f
141
142struct dmatest_thread {
143 struct list_head node;
144 struct dmatest_info *info;
145 struct task_struct *task;
146 struct dma_chan *chan;
147 u8 **srcs;
148 u8 **dsts;
149 enum dma_transaction_type type;
150 bool done;
151};
152
153struct dmatest_chan {
154 struct list_head node;
155 struct dma_chan *chan;
156 struct list_head threads;
157};
155 158
156static bool dmatest_match_channel(struct dmatest_params *params, 159static bool dmatest_match_channel(struct dmatest_params *params,
157 struct dma_chan *chan) 160 struct dma_chan *chan)
@@ -731,13 +734,24 @@ static bool filter(struct dma_chan *chan, void *param)
731 return true; 734 return true;
732} 735}
733 736
734static int __run_threaded_test(struct dmatest_info *info) 737static int run_threaded_test(struct dmatest_info *info)
735{ 738{
736 dma_cap_mask_t mask; 739 dma_cap_mask_t mask;
737 struct dma_chan *chan; 740 struct dma_chan *chan;
738 struct dmatest_params *params = &info->params; 741 struct dmatest_params *params = &info->params;
739 int err = 0; 742 int err = 0;
740 743
744 /* Copy test parameters */
745 params->buf_size = test_buf_size;
746 strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
747 strlcpy(params->device, strim(test_device), sizeof(params->device));
748 params->threads_per_chan = threads_per_chan;
749 params->max_channels = max_channels;
750 params->iterations = iterations;
751 params->xor_sources = xor_sources;
752 params->pq_sources = pq_sources;
753 params->timeout = timeout;
754
741 dma_cap_zero(mask); 755 dma_cap_zero(mask);
742 dma_cap_set(DMA_MEMCPY, mask); 756 dma_cap_set(DMA_MEMCPY, mask);
743 for (;;) { 757 for (;;) {
@@ -757,19 +771,8 @@ static int __run_threaded_test(struct dmatest_info *info)
757 return err; 771 return err;
758} 772}
759 773
760#ifndef MODULE
761static int run_threaded_test(struct dmatest_info *info)
762{
763 int ret;
764
765 mutex_lock(&info->lock);
766 ret = __run_threaded_test(info);
767 mutex_unlock(&info->lock);
768 return ret;
769}
770#endif
771 774
772static void __stop_threaded_test(struct dmatest_info *info) 775static void stop_threaded_test(struct dmatest_info *info)
773{ 776{
774 struct dmatest_chan *dtc, *_dtc; 777 struct dmatest_chan *dtc, *_dtc;
775 struct dma_chan *chan; 778 struct dma_chan *chan;
@@ -785,39 +788,22 @@ static void __stop_threaded_test(struct dmatest_info *info)
785 info->nr_channels = 0; 788 info->nr_channels = 0;
786} 789}
787 790
788static void stop_threaded_test(struct dmatest_info *info) 791static int restart_threaded_test(struct dmatest_info *info, bool run)
789{
790 mutex_lock(&info->lock);
791 __stop_threaded_test(info);
792 mutex_unlock(&info->lock);
793}
794
795static int __restart_threaded_test(struct dmatest_info *info, bool run)
796{ 792{
797 struct dmatest_params *params = &info->params; 793 /* we might be called early to set run=, defer running until all
798 794 * parameters have been evaluated
799 /* Stop any running test first */ 795 */
800 __stop_threaded_test(info); 796 if (!info->did_init)
801
802 if (run == false)
803 return 0; 797 return 0;
804 798
805 /* Copy test parameters */ 799 /* Stop any running test first */
806 params->buf_size = test_buf_size; 800 stop_threaded_test(info);
807 strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
808 strlcpy(params->device, strim(test_device), sizeof(params->device));
809 params->threads_per_chan = threads_per_chan;
810 params->max_channels = max_channels;
811 params->iterations = iterations;
812 params->xor_sources = xor_sources;
813 params->pq_sources = pq_sources;
814 params->timeout = timeout;
815 801
816 /* Run test with new parameters */ 802 /* Run test with new parameters */
817 return __run_threaded_test(info); 803 return run_threaded_test(info);
818} 804}
819 805
820static bool __is_threaded_test_run(struct dmatest_info *info) 806static bool is_threaded_test_run(struct dmatest_info *info)
821{ 807{
822 struct dmatest_chan *dtc; 808 struct dmatest_chan *dtc;
823 809
@@ -833,101 +819,61 @@ static bool __is_threaded_test_run(struct dmatest_info *info)
833 return false; 819 return false;
834} 820}
835 821
836static ssize_t dtf_read_run(struct file *file, char __user *user_buf, 822static int dmatest_run_get(char *val, const struct kernel_param *kp)
837 size_t count, loff_t *ppos)
838{ 823{
839 struct dmatest_info *info = file->private_data; 824 struct dmatest_info *info = &test_info;
840 char buf[3];
841 825
842 mutex_lock(&info->lock); 826 mutex_lock(&info->lock);
843 827 if (is_threaded_test_run(info)) {
844 if (__is_threaded_test_run(info)) { 828 dmatest_run = true;
845 buf[0] = 'Y';
846 } else { 829 } else {
847 __stop_threaded_test(info); 830 stop_threaded_test(info);
848 buf[0] = 'N'; 831 dmatest_run = false;
849 } 832 }
850
851 mutex_unlock(&info->lock); 833 mutex_unlock(&info->lock);
852 buf[1] = '\n'; 834
853 buf[2] = 0x00; 835 return param_get_bool(val, kp);
854 return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
855} 836}
856 837
857static ssize_t dtf_write_run(struct file *file, const char __user *user_buf, 838static int dmatest_run_set(const char *val, const struct kernel_param *kp)
858 size_t count, loff_t *ppos)
859{ 839{
860 struct dmatest_info *info = file->private_data; 840 struct dmatest_info *info = &test_info;
861 char buf[16]; 841 int ret;
862 bool bv;
863 int ret = 0;
864
865 if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1))))
866 return -EFAULT;
867
868 if (strtobool(buf, &bv) == 0) {
869 mutex_lock(&info->lock);
870
871 if (__is_threaded_test_run(info))
872 ret = -EBUSY;
873 else
874 ret = __restart_threaded_test(info, bv);
875 842
843 mutex_lock(&info->lock);
844 ret = param_set_bool(val, kp);
845 if (ret) {
876 mutex_unlock(&info->lock); 846 mutex_unlock(&info->lock);
847 return ret;
877 } 848 }
878 849
879 return ret ? ret : count; 850 if (is_threaded_test_run(info))
880} 851 ret = -EBUSY;
881 852 else if (dmatest_run)
882static const struct file_operations dtf_run_fops = { 853 ret = restart_threaded_test(info, dmatest_run);
883 .read = dtf_read_run,
884 .write = dtf_write_run,
885 .open = simple_open,
886 .llseek = default_llseek,
887};
888
889static int dmatest_register_dbgfs(struct dmatest_info *info)
890{
891 struct dentry *d;
892
893 d = debugfs_create_dir("dmatest", NULL);
894 if (IS_ERR(d))
895 return PTR_ERR(d);
896 if (!d)
897 goto err_root;
898 854
899 info->root = d; 855 mutex_unlock(&info->lock);
900
901 /* Run or stop threaded test */
902 debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, info,
903 &dtf_run_fops);
904
905 return 0;
906 856
907err_root: 857 return ret;
908 pr_err("Failed to initialize debugfs\n");
909 return -ENOMEM;
910} 858}
911 859
912static int __init dmatest_init(void) 860static int __init dmatest_init(void)
913{ 861{
914 struct dmatest_info *info = &test_info; 862 struct dmatest_info *info = &test_info;
915 int ret; 863 int ret = 0;
916
917 memset(info, 0, sizeof(*info));
918 864
919 mutex_init(&info->lock); 865 if (dmatest_run) {
920 INIT_LIST_HEAD(&info->channels); 866 mutex_lock(&info->lock);
867 ret = run_threaded_test(info);
868 mutex_unlock(&info->lock);
869 }
921 870
922 ret = dmatest_register_dbgfs(info); 871 /* module parameters are stable, inittime tests are started,
923 if (ret) 872 * let userspace take over 'run' control
924 return ret; 873 */
874 info->did_init = true;
925 875
926#ifdef MODULE 876 return ret;
927 return 0;
928#else
929 return run_threaded_test(info);
930#endif
931} 877}
932/* when compiled-in wait for drivers to load first */ 878/* when compiled-in wait for drivers to load first */
933late_initcall(dmatest_init); 879late_initcall(dmatest_init);
@@ -936,8 +882,9 @@ static void __exit dmatest_exit(void)
936{ 882{
937 struct dmatest_info *info = &test_info; 883 struct dmatest_info *info = &test_info;
938 884
939 debugfs_remove_recursive(info->root); 885 mutex_lock(&info->lock);
940 stop_threaded_test(info); 886 stop_threaded_test(info);
887 mutex_unlock(&info->lock);
941} 888}
942module_exit(dmatest_exit); 889module_exit(dmatest_exit);
943 890