aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2013-03-04 04:09:34 -0500
committerVinod Koul <vinod.koul@intel.com>2013-04-15 00:21:18 -0400
commitd86b2f298e6de124984f5d5817ed1e6e759b3ada (patch)
tree8e8ec1c9b6d99e7bd3920709d2166e76ac80dd07 /drivers/dma
parent95019c8c5af947f64e4a62e08a4a275bc36148ee (diff)
dmatest: append verify result to results
Comparison between buffers is stored to the dedicated structure. Note that the verify result is now accessible only via file 'results' in the debugfs. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dmatest.c182
1 files changed, 128 insertions, 54 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 3697bd49ed4c..d8ce4ecfef18 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -96,6 +96,20 @@ enum dmatest_error_type {
96 DMATEST_ET_DMA_ERROR, 96 DMATEST_ET_DMA_ERROR,
97 DMATEST_ET_DMA_IN_PROGRESS, 97 DMATEST_ET_DMA_IN_PROGRESS,
98 DMATEST_ET_VERIFY, 98 DMATEST_ET_VERIFY,
99 DMATEST_ET_VERIFY_BUF,
100};
101
102struct dmatest_verify_buffer {
103 unsigned int index;
104 u8 expected;
105 u8 actual;
106};
107
108struct dmatest_verify_result {
109 unsigned int error_count;
110 struct dmatest_verify_buffer data[MAX_ERROR_COUNT];
111 u8 pattern;
112 bool is_srcbuf;
99}; 113};
100 114
101struct dmatest_thread_result { 115struct dmatest_thread_result {
@@ -106,10 +120,11 @@ struct dmatest_thread_result {
106 unsigned int len; 120 unsigned int len;
107 enum dmatest_error_type type; 121 enum dmatest_error_type type;
108 union { 122 union {
109 unsigned long data; 123 unsigned long data;
110 dma_cookie_t cookie; 124 dma_cookie_t cookie;
111 enum dma_status status; 125 enum dma_status status;
112 int error; 126 int error;
127 struct dmatest_verify_result *vr;
113 }; 128 };
114}; 129};
115 130
@@ -246,35 +261,9 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
246 } 261 }
247} 262}
248 263
249static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 264static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
250 unsigned int counter, bool is_srcbuf) 265 unsigned int start, unsigned int end, unsigned int counter,
251{ 266 u8 pattern, bool is_srcbuf)
252 u8 diff = actual ^ pattern;
253 u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
254 const char *thread_name = current->comm;
255
256 if (is_srcbuf)
257 pr_warning("%s: srcbuf[0x%x] overwritten!"
258 " Expected %02x, got %02x\n",
259 thread_name, index, expected, actual);
260 else if ((pattern & PATTERN_COPY)
261 && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
262 pr_warning("%s: dstbuf[0x%x] not copied!"
263 " Expected %02x, got %02x\n",
264 thread_name, index, expected, actual);
265 else if (diff & PATTERN_SRC)
266 pr_warning("%s: dstbuf[0x%x] was copied!"
267 " Expected %02x, got %02x\n",
268 thread_name, index, expected, actual);
269 else
270 pr_warning("%s: dstbuf[0x%x] mismatch!"
271 " Expected %02x, got %02x\n",
272 thread_name, index, expected, actual);
273}
274
275static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
276 unsigned int end, unsigned int counter, u8 pattern,
277 bool is_srcbuf)
278{ 267{
279 unsigned int i; 268 unsigned int i;
280 unsigned int error_count = 0; 269 unsigned int error_count = 0;
@@ -282,6 +271,7 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
282 u8 expected; 271 u8 expected;
283 u8 *buf; 272 u8 *buf;
284 unsigned int counter_orig = counter; 273 unsigned int counter_orig = counter;
274 struct dmatest_verify_buffer *vb;
285 275
286 for (; (buf = *bufs); bufs++) { 276 for (; (buf = *bufs); bufs++) {
287 counter = counter_orig; 277 counter = counter_orig;
@@ -289,9 +279,12 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
289 actual = buf[i]; 279 actual = buf[i];
290 expected = pattern | (~counter & PATTERN_COUNT_MASK); 280 expected = pattern | (~counter & PATTERN_COUNT_MASK);
291 if (actual != expected) { 281 if (actual != expected) {
292 if (error_count < MAX_ERROR_COUNT) 282 if (error_count < MAX_ERROR_COUNT && vr) {
293 dmatest_mismatch(actual, pattern, i, 283 vb = &vr->data[error_count];
294 counter, is_srcbuf); 284 vb->index = i;
285 vb->expected = expected;
286 vb->actual = actual;
287 }
295 error_count++; 288 error_count++;
296 } 289 }
297 counter++; 290 counter++;
@@ -340,6 +333,30 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
340 return val % 2 ? val : val - 1; 333 return val % 2 ? val : val - 1;
341} 334}
342 335
336static char *verify_result_get_one(struct dmatest_verify_result *vr,
337 unsigned int i)
338{
339 struct dmatest_verify_buffer *vb = &vr->data[i];
340 u8 diff = vb->actual ^ vr->pattern;
341 static char buf[512];
342 char *msg;
343
344 if (vr->is_srcbuf)
345 msg = "srcbuf overwritten!";
346 else if ((vr->pattern & PATTERN_COPY)
347 && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
348 msg = "dstbuf not copied!";
349 else if (diff & PATTERN_SRC)
350 msg = "dstbuf was copied!";
351 else
352 msg = "dstbuf mismatch!";
353
354 snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
355 vb->index, vb->expected, vb->actual);
356
357 return buf;
358}
359
343static char *thread_result_get(const char *name, 360static char *thread_result_get(const char *name,
344 struct dmatest_thread_result *tr) 361 struct dmatest_thread_result *tr)
345{ 362{
@@ -355,6 +372,7 @@ static char *thread_result_get(const char *name,
355 [DMATEST_ET_DMA_IN_PROGRESS] = 372 [DMATEST_ET_DMA_IN_PROGRESS] =
356 "got completion callback (DMA_IN_PROGRESS)", 373 "got completion callback (DMA_IN_PROGRESS)",
357 [DMATEST_ET_VERIFY] = "errors", 374 [DMATEST_ET_VERIFY] = "errors",
375 [DMATEST_ET_VERIFY_BUF] = "verify errors",
358 }; 376 };
359 static char buf[512]; 377 static char buf[512];
360 378
@@ -392,6 +410,51 @@ static int thread_result_add(struct dmatest_info *info,
392 return 0; 410 return 0;
393} 411}
394 412
413static unsigned int verify_result_add(struct dmatest_info *info,
414 struct dmatest_result *r, unsigned int n,
415 unsigned int src_off, unsigned int dst_off, unsigned int len,
416 u8 **bufs, int whence, unsigned int counter, u8 pattern,
417 bool is_srcbuf)
418{
419 struct dmatest_verify_result *vr;
420 unsigned int error_count;
421 unsigned int buf_off = is_srcbuf ? src_off : dst_off;
422 unsigned int start, end;
423
424 if (whence < 0) {
425 start = 0;
426 end = buf_off;
427 } else if (whence > 0) {
428 start = buf_off + len;
429 end = info->params.buf_size;
430 } else {
431 start = buf_off;
432 end = buf_off + len;
433 }
434
435 vr = kmalloc(sizeof(*vr), GFP_KERNEL);
436 if (!vr) {
437 pr_warn("dmatest: No memory to store verify result\n");
438 return dmatest_verify(NULL, bufs, start, end, counter, pattern,
439 is_srcbuf);
440 }
441
442 vr->pattern = pattern;
443 vr->is_srcbuf = is_srcbuf;
444
445 error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
446 is_srcbuf);
447 if (error_count) {
448 vr->error_count = error_count;
449 thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
450 dst_off, len, (unsigned long)vr);
451 return error_count;
452 }
453
454 kfree(vr);
455 return 0;
456}
457
395static void result_free(struct dmatest_info *info, const char *name) 458static void result_free(struct dmatest_info *info, const char *name)
396{ 459{
397 struct dmatest_result *r, *_r; 460 struct dmatest_result *r, *_r;
@@ -404,6 +467,8 @@ static void result_free(struct dmatest_info *info, const char *name)
404 continue; 467 continue;
405 468
406 list_for_each_entry_safe(tr, _tr, &r->results, node) { 469 list_for_each_entry_safe(tr, _tr, &r->results, node) {
470 if (tr->type == DMATEST_ET_VERIFY_BUF)
471 kfree(tr->vr);
407 list_del(&tr->node); 472 list_del(&tr->node);
408 kfree(tr); 473 kfree(tr);
409 } 474 }
@@ -687,25 +752,26 @@ static int dmatest_func(void *data)
687 error_count = 0; 752 error_count = 0;
688 753
689 pr_debug("%s: verifying source buffer...\n", thread_name); 754 pr_debug("%s: verifying source buffer...\n", thread_name);
690 error_count += dmatest_verify(thread->srcs, 0, src_off, 755 error_count += verify_result_add(info, result, total_tests,
756 src_off, dst_off, len, thread->srcs, -1,
691 0, PATTERN_SRC, true); 757 0, PATTERN_SRC, true);
692 error_count += dmatest_verify(thread->srcs, src_off, 758 error_count += verify_result_add(info, result, total_tests,
693 src_off + len, src_off, 759 src_off, dst_off, len, thread->srcs, 0,
694 PATTERN_SRC | PATTERN_COPY, true); 760 src_off, PATTERN_SRC | PATTERN_COPY, true);
695 error_count += dmatest_verify(thread->srcs, src_off + len, 761 error_count += verify_result_add(info, result, total_tests,
696 params->buf_size, src_off + len, 762 src_off, dst_off, len, thread->srcs, 1,
697 PATTERN_SRC, true); 763 src_off + len, PATTERN_SRC, true);
698 764
699 pr_debug("%s: verifying dest buffer...\n", 765 pr_debug("%s: verifying dest buffer...\n", thread_name);
700 thread->task->comm); 766 error_count += verify_result_add(info, result, total_tests,
701 error_count += dmatest_verify(thread->dsts, 0, dst_off, 767 src_off, dst_off, len, thread->dsts, -1,
702 0, PATTERN_DST, false); 768 0, PATTERN_DST, false);
703 error_count += dmatest_verify(thread->dsts, dst_off, 769 error_count += verify_result_add(info, result, total_tests,
704 dst_off + len, src_off, 770 src_off, dst_off, len, thread->dsts, 0,
705 PATTERN_SRC | PATTERN_COPY, false); 771 src_off, PATTERN_SRC | PATTERN_COPY, false);
706 error_count += dmatest_verify(thread->dsts, dst_off + len, 772 error_count += verify_result_add(info, result, total_tests,
707 params->buf_size, dst_off + len, 773 src_off, dst_off, len, thread->dsts, 1,
708 PATTERN_DST, false); 774 dst_off + len, PATTERN_DST, false);
709 775
710 if (error_count) { 776 if (error_count) {
711 thread_result_add(info, result, DMATEST_ET_VERIFY, 777 thread_result_add(info, result, DMATEST_ET_VERIFY,
@@ -1085,12 +1151,20 @@ static int dtf_results_show(struct seq_file *sf, void *data)
1085 struct dmatest_info *info = sf->private; 1151 struct dmatest_info *info = sf->private;
1086 struct dmatest_result *result; 1152 struct dmatest_result *result;
1087 struct dmatest_thread_result *tr; 1153 struct dmatest_thread_result *tr;
1154 unsigned int i;
1088 1155
1089 mutex_lock(&info->results_lock); 1156 mutex_lock(&info->results_lock);
1090 list_for_each_entry(result, &info->results, node) { 1157 list_for_each_entry(result, &info->results, node) {
1091 list_for_each_entry(tr, &result->results, node) 1158 list_for_each_entry(tr, &result->results, node) {
1092 seq_printf(sf, "%s\n", 1159 seq_printf(sf, "%s\n",
1093 thread_result_get(result->name, tr)); 1160 thread_result_get(result->name, tr));
1161 if (tr->type == DMATEST_ET_VERIFY_BUF) {
1162 for (i = 0; i < tr->vr->error_count; i++) {
1163 seq_printf(sf, "\t%s\n",
1164 verify_result_get_one(tr->vr, i));
1165 }
1166 }
1167 }
1094 } 1168 }
1095 1169
1096 mutex_unlock(&info->results_lock); 1170 mutex_unlock(&info->results_lock);