summaryrefslogtreecommitdiffstats
path: root/drivers/dma/dmatest.c
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 /drivers/dma/dmatest.c
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>
Diffstat (limited to 'drivers/dma/dmatest.c')
-rw-r--r--drivers/dma/dmatest.c265
1 files changed, 106 insertions, 159 deletions
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