diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-10-26 07:12:31 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-10-26 07:12:31 +0200 |
commit | 32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e (patch) | |
tree | 7cf6cf29b564505655db004d5df11fa28c687278 /dma/nwl_loopback.c | |
parent | 39125f647c27a19abf85b25c753fc97832708d38 (diff) | |
download | pcitool-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.gz pcitool-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.bz2 pcitool-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.tar.xz pcitool-32c2f2c589c1a3ccf5dd9117538aafc6f3e0194e.zip |
Improvements of DMA engine
Diffstat (limited to 'dma/nwl_loopback.c')
-rw-r--r-- | dma/nwl_loopback.c | 132 |
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", ®val); - printf("Status1: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", ®val); - printf("Start address: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", ®val); - printf("End address: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", ®val); - printf("Status2: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", ®val); - printf("Status3: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", ®val); - 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", ®val); - printf("Status1: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9080", ®val); - printf("Start address: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9090", ®val); - printf("End address: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9100", ®val); - printf("Status2: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9110", ®val); - printf("Status3: %i 0x%lx\n", err, regval); - err = pcilib_read_register(ctx->pcilib, NULL, "reg9160", ®val); - 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); } |