|
@@ -98,20 +98,6 @@ 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 {
|
|
@@ -122,11 +108,10 @@ 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;
|
|
|
- struct dmatest_verify_result *vr;
|
|
|
+ unsigned long data;
|
|
|
+ dma_cookie_t cookie;
|
|
|
+ enum dma_status status;
|
|
|
+ int error;
|
|
|
};
|
|
|
};
|
|
|
|
|
@@ -262,9 +247,31 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-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)
|
|
|
+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_warn("%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_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
|
|
|
+ thread_name, index, expected, actual);
|
|
|
+ else if (diff & PATTERN_SRC)
|
|
|
+ pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
|
|
|
+ thread_name, index, expected, actual);
|
|
|
+ else
|
|
|
+ pr_warn("%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)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
unsigned int error_count = 0;
|
|
@@ -272,7 +279,6 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
|
|
|
u8 expected;
|
|
|
u8 *buf;
|
|
|
unsigned int counter_orig = counter;
|
|
|
- struct dmatest_verify_buffer *vb;
|
|
|
|
|
|
for (; (buf = *bufs); bufs++) {
|
|
|
counter = counter_orig;
|
|
@@ -280,12 +286,9 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
|
|
|
actual = buf[i];
|
|
|
expected = pattern | (~counter & PATTERN_COUNT_MASK);
|
|
|
if (actual != expected) {
|
|
|
- if (error_count < MAX_ERROR_COUNT && vr) {
|
|
|
- vb = &vr->data[error_count];
|
|
|
- vb->index = i;
|
|
|
- vb->expected = expected;
|
|
|
- vb->actual = actual;
|
|
|
- }
|
|
|
+ if (error_count < MAX_ERROR_COUNT)
|
|
|
+ dmatest_mismatch(actual, pattern, i,
|
|
|
+ counter, is_srcbuf);
|
|
|
error_count++;
|
|
|
}
|
|
|
counter++;
|
|
@@ -293,7 +296,7 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
|
|
|
}
|
|
|
|
|
|
if (error_count > MAX_ERROR_COUNT)
|
|
|
- pr_warning("%s: %u errors suppressed\n",
|
|
|
+ pr_warn("%s: %u errors suppressed\n",
|
|
|
current->comm, error_count - MAX_ERROR_COUNT);
|
|
|
|
|
|
return error_count;
|
|
@@ -334,30 +337,6 @@ 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)
|
|
|
{
|
|
@@ -373,7 +352,6 @@ 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];
|
|
|
|
|
@@ -415,51 +393,6 @@ 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;
|
|
@@ -472,8 +405,6 @@ 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);
|
|
|
}
|
|
@@ -755,26 +686,25 @@ static int dmatest_func(void *data)
|
|
|
error_count = 0;
|
|
|
|
|
|
pr_debug("%s: verifying source buffer...\n", thread_name);
|
|
|
- error_count += verify_result_add(info, result, total_tests,
|
|
|
- src_off, dst_off, len, thread->srcs, -1,
|
|
|
+ error_count += dmatest_verify(thread->srcs, 0, src_off,
|
|
|
0, 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_name);
|
|
|
- error_count += verify_result_add(info, result, total_tests,
|
|
|
- src_off, dst_off, len, thread->dsts, -1,
|
|
|
+ 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);
|
|
|
+
|
|
|
+ pr_debug("%s: verifying dest buffer...\n",
|
|
|
+ thread->task->comm);
|
|
|
+ error_count += dmatest_verify(thread->dsts, 0, dst_off,
|
|
|
0, 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);
|
|
|
+ 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);
|
|
|
|
|
|
if (error_count) {
|
|
|
thread_result_add(info, result, DMATEST_ET_VERIFY,
|
|
@@ -1099,20 +1029,12 @@ 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);
|