summaryrefslogtreecommitdiffstats
path: root/dma/nwl_loopback.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-10-26 07:12:31 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-10-26 07:12:31 +0200
commit32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e (patch)
tree7cf6cf29b564505655db004d5df11fa28c687278 /dma/nwl_loopback.c
parent39125f647c27a19abf85b25c753fc97832708d38 (diff)
downloadipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.gz
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.bz2
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.xz
ipecamera-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.zip
Improvements of DMA engine
Diffstat (limited to 'dma/nwl_loopback.c')
-rw-r--r--dma/nwl_loopback.c132
1 files changed, 76 insertions, 56 deletions
diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c
index a87c109..11f7f34 100644
--- a/dma/nwl_loopback.c
+++ b/dma/nwl_loopback.c
@@ -13,6 +13,8 @@
#include "nwl_defines.h"
+#define NWL_BUG_EXTRA_DATA
+
int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) {
uint32_t val;
@@ -66,11 +68,12 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
int iter, i;
int res;
int err;
- size_t bytes;
+ size_t bytes, rbytes;
uint32_t val;
uint32_t *buf, *cmp;
const char *error = NULL;
pcilib_register_value_t regval;
+ size_t packet_size, blocks;
size_t us = 0;
struct timeval start, cur;
@@ -87,8 +90,10 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
else size /= sizeof(uint32_t);
// Not supported
- if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
- else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.;
+ if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) {
+ if (direction == PCILIB_DMA_TO_DEVICE) return -1.;
+ }
+// else if ((direction == PCILIB_DMA_FROM_DEVICE)&&(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) return -1.;
// Stop Generators and drain old data
if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx);
@@ -107,63 +112,107 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
dma_nwl_enable_engine_irq(ctx, writeid);
#endif /* NWL_GENERATE_DMA_IRQ */
- dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t));
+ if (size * sizeof(uint32_t) > NWL_MAX_PACKET_SIZE) {
+ packet_size = NWL_MAX_PACKET_SIZE;
+ blocks = (size * sizeof(uint32_t)) / packet_size + (((size*sizeof(uint32_t))%packet_size)?1:0);
+ } else {
+ packet_size = size * sizeof(uint32_t);
+ blocks = 1;
+ }
+
+ dma_nwl_start_loopback(ctx, direction, packet_size);
// Allocate memory and prepare data
- buf = malloc(size * sizeof(uint32_t));
- cmp = malloc(size * sizeof(uint32_t));
+ buf = malloc(blocks * packet_size * sizeof(uint32_t));
+ cmp = malloc(blocks * packet_size * sizeof(uint32_t));
if ((!buf)||(!cmp)) {
if (buf) free(buf);
if (cmp) free(cmp);
return -1;
}
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e5);
usleep(100000);
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
+
+ // This way causes more problems with garbage
+ //pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1);
}
-//#endif /* DEBUG_HARDWARE */
// Benchmark
for (iter = 0; iter < iterations; iter++) {
memset(cmp, 0x13 + iter, size * sizeof(uint32_t));
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
}
-//#endif /* DEBUG_HARDWARE */
- gettimeofday(&start, NULL);
- if (direction&PCILIB_DMA_TO_DEVICE) {
+ if ((direction&PCILIB_DMA_TO_DEVICE)||(ctx->type != PCILIB_DMA_MODIFICATION_DEFAULT)) {
memcpy(buf, cmp, size * sizeof(uint32_t));
+ if (direction&PCILIB_DMA_TO_DEVICE) {
+ gettimeofday(&start, NULL);
+ }
+
err = pcilib_write_dma(ctx->pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes);
if ((err)||(bytes != size * sizeof(uint32_t))) {
error = "Write failed";
- break;
+ break;
+ }
+
+ if (direction&PCILIB_DMA_TO_DEVICE) {
+ // wait written
+ if (direction == PCILIB_DMA_TO_DEVICE) {
+ dma_nwl_wait_completion(ctx, writeid, PCILIB_DMA_TIMEOUT);
+ }
+ gettimeofday(&cur, NULL);
+ us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
}
}
-//#ifdef DEBUG_HARDWARE
if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1);
}
-//#endif /* DEBUG_HARDWARE */
memset(buf, 0, size * sizeof(uint32_t));
-
- err = pcilib_read_dma(ctx->pcilib, readid, addr, size * sizeof(uint32_t), buf, &bytes);
- gettimeofday(&cur, NULL);
- us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
+ if (direction&PCILIB_DMA_FROM_DEVICE) {
+ gettimeofday(&start, NULL);
+ }
+
+ for (i = 0, bytes = 0; i < blocks; i++) {
+#ifdef NWL_BUG_EXTRA_DATA
+ retry:
+#endif
+
+ err = pcilib_read_dma(ctx->pcilib, readid, addr, packet_size * sizeof(uint32_t), buf + (bytes>>2), &rbytes);
+ if ((err)||(rbytes%sizeof(uint32_t))) {
+ break;
+ }
+#ifdef NWL_BUG_EXTRA_DATA
+ else if (rbytes == 8) {
+ goto retry;
+ }
+#endif
+ bytes += rbytes;
+ }
+
+ if (direction&PCILIB_DMA_FROM_DEVICE) {
+ gettimeofday(&cur, NULL);
+ us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
+ }
+#ifdef NWL_BUG_EXTRA_DATA
+ if ((err)||((bytes != size * sizeof(uint32_t))&&((bytes - 8) != size * sizeof(uint32_t)))) {
+#else
if ((err)||(bytes != size * sizeof(uint32_t))) {
- error = "Read failed";
- break;
+#endif
+ printf("Expected: %zu bytes, but %zu read, error: %i\n", size * sizeof(uint32_t), bytes, err);
+ error = "Read failed";
+ break;
}
+#ifndef NWL_BUG_EXTRA_DATA
if (direction == PCILIB_DMA_BIDIRECTIONAL) {
res = memcmp(buf, cmp, size * sizeof(uint32_t));
if (res) {
@@ -171,7 +220,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
if (buf[i] != cmp[i]) break;
bytes = i;
- printf("Expected: *%lx, Written at position %lu:", 0x13 + iter, bytes);
+ printf("Expected: *0x%lx, Written at dword %lu:", 0x13 + iter, bytes);
for (; (i < size)&&(i < (bytes + 16)); i++) {
if (((i - bytes)%8)==0) printf("\n");
printf("% 10lx", buf[i]);
@@ -182,41 +231,12 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
break;
}
}
-
-#ifdef DEBUG_HARDWARE
- puts("====================================");
-
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", &regval);
- printf("Status1: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", &regval);
- printf("Start address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", &regval);
- printf("End address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", &regval);
- printf("Status2: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", &regval);
- printf("Status3: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", &regval);
- printf("Add_rd_ddr: %i 0x%lx\n", err, regval);
-#endif /* DEBUG_HARDWARE */
-
+#endif
}
-#ifdef DEBUG_HARDWARE
- puts("------------------------------------------------");
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9050", &regval);
- printf("Status1: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", &regval);
- printf("Start address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", &regval);
- printf("End address: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", &regval);
- printf("Status2: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", &regval);
- printf("Status3: %i 0x%lx\n", err, regval);
- err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", &regval);
- printf("Add_rd_ddr: %i 0x%lx\n", err, regval);
-#endif /* DEBUG_HARDWARE */
+ if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) {
+ pcilib_write_register(ctx->pcilib, NULL, "control", 0x1e1);
+ }
if (error) {
pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, iter, err, bytes);
@@ -238,5 +258,5 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
free(cmp);
free(buf);
- return error?-1:(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us);
+ return /*error?-1:*/(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us);
}