diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-14 06:01:27 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-14 06:01:27 +0200 |
commit | f4ad2df2209acac66f3df47d847f1f714283feab (patch) | |
tree | 23da0368acbb6c15cdebd2a35808cd6bbe99b8ae /dma/nwl_loopback.c | |
parent | b492b1aac3d12683ccbc973b08b023ba0466cbec (diff) | |
download | pcitool-f4ad2df2209acac66f3df47d847f1f714283feab.tar.gz pcitool-f4ad2df2209acac66f3df47d847f1f714283feab.tar.bz2 pcitool-f4ad2df2209acac66f3df47d847f1f714283feab.tar.xz pcitool-f4ad2df2209acac66f3df47d847f1f714283feab.zip |
First iteration of work to preserve DMA state between executions
Diffstat (limited to 'dma/nwl_loopback.c')
-rw-r--r-- | dma/nwl_loopback.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c index a31bd08..3c2c124 100644 --- a/dma/nwl_loopback.c +++ b/dma/nwl_loopback.c @@ -52,3 +52,176 @@ int dma_nwl_stop_loopback(nwl_dma_t *ctx) { return 0; } + +double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dma, uintptr_t addr, size_t size, size_t iterations, pcilib_dma_direction_t direction) { + int i; + int res; + int err; + size_t bytes; + uint32_t val; + uint32_t *buf, *cmp; + const char *error = NULL; + pcilib_register_value_t regval; + + size_t us = 0; + struct timeval start, cur; + + nwl_dma_t *ctx = (nwl_dma_t*)vctx; + + pcilib_dma_engine_t readid = pcilib_find_dma_by_addr(ctx->pcilib, PCILIB_DMA_FROM_DEVICE, dma); + pcilib_dma_engine_t writeid = pcilib_find_dma_by_addr(ctx->pcilib, PCILIB_DMA_TO_DEVICE, dma); + + char *read_base = ctx->engines[readid].base_addr; + char *write_base = ctx->engines[writeid].base_addr; + + if (size%sizeof(uint32_t)) size = 1 + size / sizeof(uint32_t); + 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.; + + // Stop Generators and drain old data + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); +// dma_nwl_stop_engine(ctx, readid); // DS: replace with something better + + __sync_synchronize(); + + err = pcilib_skip_dma(ctx->pcilib, readid); + if (err) { + pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine"); + return err; + } + +#ifdef NWL_GENERATE_DMA_IRQ + dma_nwl_enable_engine_irq(ctx, readid); + dma_nwl_enable_engine_irq(ctx, writeid); +#endif /* NWL_GENERATE_DMA_IRQ */ + + + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) { + dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t)); + } + + // Allocate memory and prepare data + buf = malloc(size * sizeof(uint32_t)); + cmp = malloc(size * sizeof(uint32_t)); + if ((!buf)||(!cmp)) { + if (buf) free(buf); + if (cmp) free(cmp); + return -1; + } + + memset(cmp, 0x13, size * sizeof(uint32_t)); + + +#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); + } +#endif /* DEBUG_HARDWARE */ + + // Benchmark + for (i = 0; i < iterations; i++) { +#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) { + memcpy(buf, cmp, size * sizeof(uint32_t)); + + 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; + } + } + +#ifdef DEBUG_HARDWARE + if (ctx->type == PCILIB_NWL_MODIFICATION_IPECAMERA) { + //usleep(1000000); + pcilib_write_register(ctx->pcilib, NULL, "control", 0x3e1); + } + + memset(buf, 0, size * sizeof(uint32_t)); +#endif /* DEBUG_HARDWARE */ + + 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 ((err)||(bytes != size * sizeof(uint32_t))) { + error = "Read failed"; + break; + } + + if (direction == PCILIB_DMA_BIDIRECTIONAL) { + res = memcmp(buf, cmp, size * sizeof(uint32_t)); + if (res) { + error = "Written and read values does not match"; + 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 */ + + } + +#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 (error) { + pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, i, err, bytes); + } + +#ifdef NWL_GENERATE_DMA_IRQ + dma_nwl_disable_engine_irq(ctx, writeid); + dma_nwl_disable_engine_irq(ctx, readid); +#endif /* NWL_GENERATE_DMA_IRQ */ + + if (ctx->type == PCILIB_DMA_MODIFICATION_DEFAULT) dma_nwl_stop_loopback(ctx); + + __sync_synchronize(); + + if (direction == PCILIB_DMA_FROM_DEVICE) { + pcilib_skip_dma(ctx->pcilib, readid); + } + + free(cmp); + free(buf); + + return error?-1:(1. * size * sizeof(uint32_t) * iterations * 1000000) / (1024. * 1024. * us); +} |