aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-samsung/dma_m2m_test.c
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2012-09-28 13:46:28 -0400
committerChristopher Kenna <cjk@cs.unc.edu>2012-09-28 14:50:15 -0400
commitdaa22703f14c007e93b464c45fa60019a36f546d (patch)
treea1a130b6e128dc9d57c35c026977e1b4953105e1 /arch/arm/plat-samsung/dma_m2m_test.c
parent5aa287dcf1b5879aa0150b0511833c52885f5b4c (diff)
Apply k4412 kernel from HardKernel for ODROID-X.
Diffstat (limited to 'arch/arm/plat-samsung/dma_m2m_test.c')
-rw-r--r--arch/arm/plat-samsung/dma_m2m_test.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/arch/arm/plat-samsung/dma_m2m_test.c b/arch/arm/plat-samsung/dma_m2m_test.c
new file mode 100644
index 00000000000..b1ca128e6a4
--- /dev/null
+++ b/arch/arm/plat-samsung/dma_m2m_test.c
@@ -0,0 +1,323 @@
1/*
2 * Copyright (C) 2010 Samsung Electronics Co. Ltd.
3 * Jaswinder Singh <jassi.brar@samsung.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * MemToMem DMA Xfer Test Driver for S3C DMA API
20 *
21 */
22#include <linux/init.h>
23#include <linux/kthread.h>
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/wait.h>
27#include <linux/slab.h>
28#include <linux/dma-mapping.h>
29
30#include <mach/dma.h>
31
32#define XFER_UNIT 1024
33
34static unsigned int xfer_size = 256;
35module_param(xfer_size, uint, S_IRUGO);
36MODULE_PARM_DESC(xfer_size, "Size of each DMA enqueue request in KB");
37
38#define DMATEST_BRSTSZ 1
39static unsigned short burst = 1;
40module_param(burst, ushort, S_IRUGO);
41MODULE_PARM_DESC(burst, "For which parts of API to calc performance");
42
43static unsigned short perf_test = 1;
44module_param(perf_test, ushort, S_IRUGO);
45MODULE_PARM_DESC(perf_test, "For which parts of API to calc performance");
46
47static unsigned int sec = 60 * 60; /* 1 hour by default */
48module_param(sec, uint, S_IRUGO);
49MODULE_PARM_DESC(sec, "Number of seconds to run the test (default: 24hr)");
50
51static unsigned int channels = 10000; /* Use all channels by default */
52module_param(channels, uint, S_IRUGO);
53MODULE_PARM_DESC(channels, "Number of channels to test (default: 8)");
54
55struct s3cdma_thread {
56 unsigned id; /* For Channel index */
57 struct task_struct *task;
58#define SRC 0
59#define DST 1
60 void *buff_cpu[2]; /* CPU address of the Source & Destination buffer */
61 dma_addr_t buff_phys[2]; /* Physical address of the Source & Destination buffer */
62 unsigned long jiffies;
63 int stopped;
64 enum s3c2410_dma_buffresult res;
65 int size;
66 unsigned done;
67 struct s3c2410_dma_client cl;
68 struct completion xfer_cmplt;
69 struct list_head node;
70};
71
72static unsigned int delta;
73static unsigned long cycles, maxtime;
74static LIST_HEAD(channel_list);
75
76void s3cdma_cb(struct s3c2410_dma_chan *chan, void *buf_id,
77 int size, enum s3c2410_dma_buffresult res)
78{
79 struct s3cdma_thread *thread = buf_id;
80
81 thread->res = res;
82 thread->size = size;
83
84 complete(&thread->xfer_cmplt);
85}
86
87static void dmatest_init_buf(u32 buf[], int clr, unsigned int bytes)
88{
89 unsigned int i;
90
91 for (i = 0; i < bytes / 4; i++)
92 buf[i] = clr ? 0 : i;
93}
94
95static bool dmatest_buf_same(u32 src[], u32 dst[], unsigned int bytes)
96{
97 unsigned int i;
98
99 for (i = 0; i < (bytes - delta) / 4; i++)
100 if (src[i] != dst[i])
101 return false;
102
103 for (; i < bytes / 4; i++)
104 if (dst[i])
105 return false;
106
107 return true;
108}
109
110static int dmatest_func(void *data)
111{
112 struct s3cdma_thread *thread = data;
113 enum dma_ch chan = DMACH_MTOM_0 + thread->id;
114 unsigned long tout = jiffies + msecs_to_jiffies(sec * 1000);
115 int src_idx = 0;
116 unsigned val;
117
118 thread->jiffies = jiffies;
119 thread->done = 0;
120
121 while (!kthread_should_stop() && time_before(jiffies, tout)) {
122
123 u32 *srcbuf = thread->buff_cpu[src_idx];
124 u32 *dstbuf = thread->buff_cpu[1 - src_idx];
125
126 if (!perf_test) {
127 dmatest_init_buf(srcbuf, 0, xfer_size);
128 dmatest_init_buf(dstbuf, 1, xfer_size);
129 delta = 1024;
130 }
131
132 s3c2410_dma_devconfig(chan, S3C_DMA_MEM2MEM,
133 thread->buff_phys[src_idx]);
134
135 s3c2410_dma_enqueue(chan, (void *)thread,
136 thread->buff_phys[1 - src_idx], xfer_size - delta);
137
138 s3c2410_dma_ctrl(chan, S3C2410_DMAOP_START);
139
140 val = wait_for_completion_timeout(&thread->xfer_cmplt, msecs_to_jiffies(5*1000));
141 if (!val) {
142 dma_addr_t src, dst;
143 s3c2410_dma_getposition(DMACH_MTOM_0 + thread->id,
144 &src, &dst);
145
146 printk("\n%s:%d Thrd-%u Done-%u <%x,%x>/<%x,%x>\n",
147 __func__, __LINE__, thread->id, thread->done,
148 src, dst, thread->buff_phys[src_idx], thread->buff_phys[1 - src_idx]);
149 break;
150 }
151
152 if (thread->res != S3C2410_RES_OK
153 || thread->size != xfer_size - delta) {
154 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Cycle-%u Res-%u Xfer_size-%d!\n",
155 thread->id, thread->done, thread->res, thread->size);
156 } else {
157 thread->done++;
158 }
159
160 if (!perf_test &&
161 !dmatest_buf_same(srcbuf, dstbuf, xfer_size)) {
162 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Cycle-%u Xfer_cmp failed!\n",
163 thread->id, thread->done);
164 break;
165 }
166
167 src_idx = 1 - src_idx;
168 }
169
170 thread->jiffies = jiffies - thread->jiffies;
171
172 thread->stopped = 1;
173
174 return 0;
175}
176
177static int __init dmatest_init(void)
178{
179 struct s3cdma_thread *thread;
180 int ret, i = 0;
181
182 xfer_size *= XFER_UNIT;
183
184 if (sec < 5) {
185 sec = 5;
186 printk(KERN_INFO "S3C DMA M2M Test: Using 5secs test time\n");
187 }
188
189 while (i < 10) {
190 if (burst == (1 << i))
191 break;
192 i++;
193 }
194 /* If invalid burst value provided */
195 if (i == 10) {
196 burst = 1;
197 printk(KERN_INFO "S3C DMA M2M Test: Using 1 burst size\n");
198 }
199
200 for (i = 0; i < channels; i++) {
201 thread = kzalloc(sizeof(struct s3cdma_thread), GFP_KERNEL);
202 if (!thread) {
203 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for channel\n", i);
204 goto thrd_alloc_err;
205 }
206
207 thread->buff_cpu[SRC] = dma_alloc_coherent(NULL, xfer_size,
208 &thread->buff_phys[SRC], GFP_KERNEL);
209 if (!thread->buff_cpu[SRC]) {
210 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for src buff\n", i);
211 goto src_alloc_err;
212 }
213
214 thread->buff_cpu[DST] = dma_alloc_coherent(NULL, xfer_size,
215 &thread->buff_phys[DST], GFP_KERNEL);
216 if (!thread->buff_cpu[DST]) {
217 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u No memory for dst buff\n", i);
218 goto dst_alloc_err;
219 }
220
221 dmatest_init_buf(thread->buff_cpu[SRC], 0, xfer_size);
222 dmatest_init_buf(thread->buff_cpu[DST], 1, xfer_size);
223
224 thread->id = i;
225 thread->cl.name = (char *) thread;
226 thread->stopped = 0;
227
228 init_completion(&thread->xfer_cmplt);
229
230 ret = s3c2410_dma_request(DMACH_MTOM_0 + thread->id,
231 &thread->cl, NULL);
232 if (ret) {
233 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%d acq(%d)\n", i, ret);
234 goto thrd_dma_acq_err;
235 }
236
237 s3c2410_dma_set_buffdone_fn(DMACH_MTOM_0 + thread->id, s3cdma_cb);
238
239 ret = s3c2410_dma_config(DMACH_MTOM_0 + thread->id, burst);
240 if (ret) {
241 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%d config(%d)\n", i, ret);
242 goto thrd_dma_cfg_err;
243 }
244
245 thread->task = kthread_run(dmatest_func, thread,
246 "dma-m2m-test%u", i);
247 if (IS_ERR(thread->task)) {
248 printk(KERN_INFO "S3C DMA M2M Test: Failed to run thread dma-m2m-test%u\n", i);
249 goto thrd_run_err;
250 }
251
252 list_add_tail(&thread->node, &channel_list);
253
254 continue;
255
256thrd_run_err:
257thrd_dma_cfg_err:
258 s3c2410_dma_free(DMACH_MTOM_0 + thread->id, &thread->cl);
259thrd_dma_acq_err:
260 dma_free_coherent(NULL, xfer_size,
261 thread->buff_cpu[DST], thread->buff_phys[DST]);
262dst_alloc_err:
263 dma_free_coherent(NULL, xfer_size,
264 thread->buff_cpu[SRC], thread->buff_phys[SRC]);
265src_alloc_err:
266 kfree(thread);
267thrd_alloc_err:
268 break;
269 }
270
271 printk(KERN_INFO "S3C DMA M2M Test: Testing with %u Channels\n", i);
272
273 return 0;
274}
275module_init(dmatest_init);
276
277static void __exit dmatest_exit(void)
278{
279 struct s3cdma_thread *thread;
280
281 while (!list_empty(&channel_list)) {
282 thread = list_entry(channel_list.next,
283 struct s3cdma_thread, node);
284
285 list_del(&thread->node);
286
287 if (perf_test && !dmatest_buf_same(thread->buff_cpu[SRC],
288 thread->buff_cpu[DST], xfer_size))
289 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u: Xfer_cmp failed!\n", thread->id);
290
291 if (!thread->stopped)
292 kthread_stop(thread->task);
293
294 if (jiffies_to_msecs(thread->jiffies) > maxtime)
295 maxtime = jiffies_to_msecs(thread->jiffies);
296
297 cycles += thread->done;
298
299 printk(KERN_INFO "S3C DMA M2M Test: Thrd-%u %ux%u Kb in %ums\n",
300 thread->id, thread->done, xfer_size / XFER_UNIT,
301 jiffies_to_msecs(thread->jiffies));
302
303 s3c2410_dma_free(DMACH_MTOM_0 + thread->id, &thread->cl);
304
305 dma_free_coherent(NULL, xfer_size,
306 thread->buff_cpu[DST], thread->buff_phys[DST]);
307
308 dma_free_coherent(NULL, xfer_size,
309 thread->buff_cpu[SRC], thread->buff_phys[SRC]);
310
311 kfree(thread);
312 }
313
314 printk(KERN_INFO "S3C DMA M2M Test: Overall %lux%u Kb in %lums\n",
315 cycles, xfer_size / XFER_UNIT, maxtime);
316 printk(KERN_INFO "S3C DMA M2M Test: %lu MB/Sec\n",
317 cycles * 1000 / maxtime * xfer_size / XFER_UNIT / 1024);
318}
319module_exit(dmatest_exit);
320
321MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
322MODULE_DESCRIPTION("S3C DMA MemToMem Test Driver");
323MODULE_LICENSE("GPL");