diff options
author | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-28 13:46:28 -0400 |
---|---|---|
committer | Christopher Kenna <cjk@cs.unc.edu> | 2012-09-28 14:50:15 -0400 |
commit | daa22703f14c007e93b464c45fa60019a36f546d (patch) | |
tree | a1a130b6e128dc9d57c35c026977e1b4953105e1 /arch/arm/plat-samsung/dma_m2m_test.c | |
parent | 5aa287dcf1b5879aa0150b0511833c52885f5b4c (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.c | 323 |
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 | |||
34 | static unsigned int xfer_size = 256; | ||
35 | module_param(xfer_size, uint, S_IRUGO); | ||
36 | MODULE_PARM_DESC(xfer_size, "Size of each DMA enqueue request in KB"); | ||
37 | |||
38 | #define DMATEST_BRSTSZ 1 | ||
39 | static unsigned short burst = 1; | ||
40 | module_param(burst, ushort, S_IRUGO); | ||
41 | MODULE_PARM_DESC(burst, "For which parts of API to calc performance"); | ||
42 | |||
43 | static unsigned short perf_test = 1; | ||
44 | module_param(perf_test, ushort, S_IRUGO); | ||
45 | MODULE_PARM_DESC(perf_test, "For which parts of API to calc performance"); | ||
46 | |||
47 | static unsigned int sec = 60 * 60; /* 1 hour by default */ | ||
48 | module_param(sec, uint, S_IRUGO); | ||
49 | MODULE_PARM_DESC(sec, "Number of seconds to run the test (default: 24hr)"); | ||
50 | |||
51 | static unsigned int channels = 10000; /* Use all channels by default */ | ||
52 | module_param(channels, uint, S_IRUGO); | ||
53 | MODULE_PARM_DESC(channels, "Number of channels to test (default: 8)"); | ||
54 | |||
55 | struct 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 | |||
72 | static unsigned int delta; | ||
73 | static unsigned long cycles, maxtime; | ||
74 | static LIST_HEAD(channel_list); | ||
75 | |||
76 | void 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 | |||
87 | static 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 | |||
95 | static 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 | |||
110 | static 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 | |||
177 | static 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 | |||
256 | thrd_run_err: | ||
257 | thrd_dma_cfg_err: | ||
258 | s3c2410_dma_free(DMACH_MTOM_0 + thread->id, &thread->cl); | ||
259 | thrd_dma_acq_err: | ||
260 | dma_free_coherent(NULL, xfer_size, | ||
261 | thread->buff_cpu[DST], thread->buff_phys[DST]); | ||
262 | dst_alloc_err: | ||
263 | dma_free_coherent(NULL, xfer_size, | ||
264 | thread->buff_cpu[SRC], thread->buff_phys[SRC]); | ||
265 | src_alloc_err: | ||
266 | kfree(thread); | ||
267 | thrd_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 | } | ||
275 | module_init(dmatest_init); | ||
276 | |||
277 | static 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 | } | ||
319 | module_exit(dmatest_exit); | ||
320 | |||
321 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); | ||
322 | MODULE_DESCRIPTION("S3C DMA MemToMem Test Driver"); | ||
323 | MODULE_LICENSE("GPL"); | ||