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>
This commit is contained in:
Andy Shevchenko
2013-03-04 11:09:34 +02:00
committed by Vinod Koul
parent 95019c8c5a
commit d86b2f298e
2 changed files with 131 additions and 55 deletions

View File

@@ -96,6 +96,20 @@ enum dmatest_error_type {
DMATEST_ET_DMA_ERROR,
DMATEST_ET_DMA_IN_PROGRESS,
DMATEST_ET_VERIFY,
DMATEST_ET_VERIFY_BUF,
};
struct dmatest_verify_buffer {
unsigned int index;
u8 expected;
u8 actual;
};
struct dmatest_verify_result {
unsigned int error_count;
struct dmatest_verify_buffer data[MAX_ERROR_COUNT];
u8 pattern;
bool is_srcbuf;
};
struct dmatest_thread_result {
@@ -106,10 +120,11 @@ struct dmatest_thread_result {
unsigned int len;
enum dmatest_error_type type;
union {
unsigned long data;
dma_cookie_t cookie;
enum dma_status status;
int error;
unsigned long data;
dma_cookie_t cookie;
enum dma_status status;
int error;
struct dmatest_verify_result *vr;
};
};
@@ -246,35 +261,9 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
}
}
static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
unsigned int counter, bool is_srcbuf)
{
u8 diff = actual ^ pattern;
u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
const char *thread_name = current->comm;
if (is_srcbuf)
pr_warning("%s: srcbuf[0x%x] overwritten!"
" Expected %02x, got %02x\n",
thread_name, index, expected, actual);
else if ((pattern & PATTERN_COPY)
&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
pr_warning("%s: dstbuf[0x%x] not copied!"
" Expected %02x, got %02x\n",
thread_name, index, expected, actual);
else if (diff & PATTERN_SRC)
pr_warning("%s: dstbuf[0x%x] was copied!"
" Expected %02x, got %02x\n",
thread_name, index, expected, actual);
else
pr_warning("%s: dstbuf[0x%x] mismatch!"
" Expected %02x, got %02x\n",
thread_name, index, expected, actual);
}
static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
unsigned int end, unsigned int counter, u8 pattern,
bool is_srcbuf)
static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
unsigned int start, unsigned int end, unsigned int counter,
u8 pattern, bool is_srcbuf)
{
unsigned int i;
unsigned int error_count = 0;
@@ -282,6 +271,7 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
u8 expected;
u8 *buf;
unsigned int counter_orig = counter;
struct dmatest_verify_buffer *vb;
for (; (buf = *bufs); bufs++) {
counter = counter_orig;
@@ -289,9 +279,12 @@ static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
actual = buf[i];
expected = pattern | (~counter & PATTERN_COUNT_MASK);
if (actual != expected) {
if (error_count < MAX_ERROR_COUNT)
dmatest_mismatch(actual, pattern, i,
counter, is_srcbuf);
if (error_count < MAX_ERROR_COUNT && vr) {
vb = &vr->data[error_count];
vb->index = i;
vb->expected = expected;
vb->actual = actual;
}
error_count++;
}
counter++;
@@ -340,6 +333,30 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
return val % 2 ? val : val - 1;
}
static char *verify_result_get_one(struct dmatest_verify_result *vr,
unsigned int i)
{
struct dmatest_verify_buffer *vb = &vr->data[i];
u8 diff = vb->actual ^ vr->pattern;
static char buf[512];
char *msg;
if (vr->is_srcbuf)
msg = "srcbuf overwritten!";
else if ((vr->pattern & PATTERN_COPY)
&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
msg = "dstbuf not copied!";
else if (diff & PATTERN_SRC)
msg = "dstbuf was copied!";
else
msg = "dstbuf mismatch!";
snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
vb->index, vb->expected, vb->actual);
return buf;
}
static char *thread_result_get(const char *name,
struct dmatest_thread_result *tr)
{
@@ -355,6 +372,7 @@ static char *thread_result_get(const char *name,
[DMATEST_ET_DMA_IN_PROGRESS] =
"got completion callback (DMA_IN_PROGRESS)",
[DMATEST_ET_VERIFY] = "errors",
[DMATEST_ET_VERIFY_BUF] = "verify errors",
};
static char buf[512];
@@ -392,6 +410,51 @@ static int thread_result_add(struct dmatest_info *info,
return 0;
}
static unsigned int verify_result_add(struct dmatest_info *info,
struct dmatest_result *r, unsigned int n,
unsigned int src_off, unsigned int dst_off, unsigned int len,
u8 **bufs, int whence, unsigned int counter, u8 pattern,
bool is_srcbuf)
{
struct dmatest_verify_result *vr;
unsigned int error_count;
unsigned int buf_off = is_srcbuf ? src_off : dst_off;
unsigned int start, end;
if (whence < 0) {
start = 0;
end = buf_off;
} else if (whence > 0) {
start = buf_off + len;
end = info->params.buf_size;
} else {
start = buf_off;
end = buf_off + len;
}
vr = kmalloc(sizeof(*vr), GFP_KERNEL);
if (!vr) {
pr_warn("dmatest: No memory to store verify result\n");
return dmatest_verify(NULL, bufs, start, end, counter, pattern,
is_srcbuf);
}
vr->pattern = pattern;
vr->is_srcbuf = is_srcbuf;
error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
is_srcbuf);
if (error_count) {
vr->error_count = error_count;
thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
dst_off, len, (unsigned long)vr);
return error_count;
}
kfree(vr);
return 0;
}
static void result_free(struct dmatest_info *info, const char *name)
{
struct dmatest_result *r, *_r;
@@ -404,6 +467,8 @@ static void result_free(struct dmatest_info *info, const char *name)
continue;
list_for_each_entry_safe(tr, _tr, &r->results, node) {
if (tr->type == DMATEST_ET_VERIFY_BUF)
kfree(tr->vr);
list_del(&tr->node);
kfree(tr);
}
@@ -687,25 +752,26 @@ static int dmatest_func(void *data)
error_count = 0;
pr_debug("%s: verifying source buffer...\n", thread_name);
error_count += dmatest_verify(thread->srcs, 0, src_off,
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->srcs, -1,
0, PATTERN_SRC, true);
error_count += dmatest_verify(thread->srcs, src_off,
src_off + len, src_off,
PATTERN_SRC | PATTERN_COPY, true);
error_count += dmatest_verify(thread->srcs, src_off + len,
params->buf_size, src_off + len,
PATTERN_SRC, true);
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->srcs, 0,
src_off, PATTERN_SRC | PATTERN_COPY, true);
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->srcs, 1,
src_off + len, PATTERN_SRC, true);
pr_debug("%s: verifying dest buffer...\n",
thread->task->comm);
error_count += dmatest_verify(thread->dsts, 0, dst_off,
pr_debug("%s: verifying dest buffer...\n", thread_name);
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->dsts, -1,
0, PATTERN_DST, false);
error_count += dmatest_verify(thread->dsts, dst_off,
dst_off + len, src_off,
PATTERN_SRC | PATTERN_COPY, false);
error_count += dmatest_verify(thread->dsts, dst_off + len,
params->buf_size, dst_off + len,
PATTERN_DST, false);
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->dsts, 0,
src_off, PATTERN_SRC | PATTERN_COPY, false);
error_count += verify_result_add(info, result, total_tests,
src_off, dst_off, len, thread->dsts, 1,
dst_off + len, PATTERN_DST, false);
if (error_count) {
thread_result_add(info, result, DMATEST_ET_VERIFY,
@@ -1085,12 +1151,20 @@ static int dtf_results_show(struct seq_file *sf, void *data)
struct dmatest_info *info = sf->private;
struct dmatest_result *result;
struct dmatest_thread_result *tr;
unsigned int i;
mutex_lock(&info->results_lock);
list_for_each_entry(result, &info->results, node) {
list_for_each_entry(tr, &result->results, node)
list_for_each_entry(tr, &result->results, node) {
seq_printf(sf, "%s\n",
thread_result_get(result->name, tr));
if (tr->type == DMATEST_ET_VERIFY_BUF) {
for (i = 0; i < tr->vr->error_count; i++) {
seq_printf(sf, "\t%s\n",
verify_result_get_one(tr->vr, i));
}
}
}
}
mutex_unlock(&info->results_lock);