aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/dmatest.txt6
-rw-r--r--drivers/dma/dmatest.c182
2 files changed, 132 insertions, 56 deletions
diff --git a/Documentation/dmatest.txt b/Documentation/dmatest.txt
index d05782b26a2e..279ac0a8c5b1 100644
--- a/Documentation/dmatest.txt
+++ b/Documentation/dmatest.txt
@@ -75,5 +75,7 @@ The message format is unified across the different types of errors. A number in
75the parens represents additional information, e.g. error code, error counter, 75the parens represents additional information, e.g. error code, error counter,
76or status. 76or status.
77 77
78Note that the buffer comparison is done in the old way, i.e. data is not 78Comparison between buffers is stored to the dedicated structure.
79collected and just printed out. 79
80Note that the verify result is now accessible only via file 'results' in the
81debugfs.
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);