summaryrefslogtreecommitdiffstats
path: root/dma
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-02-03 15:29:35 +0100
committerSuren A. Chilingaryan <csa@suren.me>2015-02-03 15:29:35 +0100
commitfe6a3fc5e79ed76c5f7bf84482698850aaedbae9 (patch)
treee9395f1c8f91e999c5b6ef7a22d701114fd14ea2 /dma
parent3b3f049e8dfd7314239a4f489884648b2808d735 (diff)
downloadpcitool-fe6a3fc5e79ed76c5f7bf84482698850aaedbae9.tar.gz
pcitool-fe6a3fc5e79ed76c5f7bf84482698850aaedbae9.tar.bz2
pcitool-fe6a3fc5e79ed76c5f7bf84482698850aaedbae9.tar.xz
pcitool-fe6a3fc5e79ed76c5f7bf84482698850aaedbae9.zip
Several fixes in IPEDMA driver and its benchmarking code
Diffstat (limited to 'dma')
-rw-r--r--dma/ipe.c77
-rw-r--r--dma/ipe_private.h1
2 files changed, 72 insertions, 6 deletions
diff --git a/dma/ipe.c b/dma/ipe.c
index 23c94d0..f2c2f3d 100644
--- a/dma/ipe.c
+++ b/dma/ipe.c
@@ -143,7 +143,8 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
fclose(f);
#else /* IPEDMA_BUG_DMARD */
RD(IPEDMA_REG_LAST_READ, value);
- if (value == IPEDMA_DMA_PAGES) value = 0;
+ // Numbered from 1 in FPGA
+ value--;
#endif /* IPEDMA_BUG_DMARD */
ctx->last_read = value;
@@ -177,7 +178,7 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
WR(IPEDMA_REG_PAGE_COUNT, 0);
// Setting current read position and configuring progress register
- WR(IPEDMA_REG_LAST_READ, IPEDMA_DMA_PAGES - 2 + 1);
+ WR(IPEDMA_REG_LAST_READ, IPEDMA_DMA_PAGES);
WR(IPEDMA_REG_UPDATE_ADDR, pcilib_kmem_get_block_ba(ctx->pcilib, desc, 0));
// Instructing DMA engine that writting should start from the first DMA page
@@ -366,8 +367,8 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
do {
switch (ret&PCILIB_STREAMING_TIMEOUT_MASK) {
- case PCILIB_STREAMING_CONTINUE: wait = PCILIB_DMA_TIMEOUT; break;
- case PCILIB_STREAMING_WAIT: wait = timeout; break;
+ case PCILIB_STREAMING_CONTINUE: wait = IPEDMA_DMA_TIMEOUT; break;
+ case PCILIB_STREAMING_WAIT: wait = ((timeout<IPEDMA_DMA_TIMEOUT)?IPEDMA_DMA_TIMEOUT:timeout); break;
// case PCILIB_STREAMING_CHECK: wait = 0; break;
}
@@ -376,6 +377,7 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
#endif /* IPEDMA_DEBUG */
gettimeofday(&start, NULL);
+ memcpy(&cur, &start, sizeof(struct timeval));
while (((*last_written_addr_ptr == 0)||(ctx->last_read_addr == (*last_written_addr_ptr)))&&((wait == PCILIB_TIMEOUT_INFINITE)||(((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)) < wait))) {
usleep(10);
gettimeofday(&cur, NULL);
@@ -401,7 +403,8 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
// DS: Fixme, it looks like we can avoid calling this for the sake of performance
// pcilib_kmem_sync_block(ctx->pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read);
- WR(IPEDMA_REG_LAST_READ, ctx->last_read + 1);
+ // Numbered from 1
+ WR(IPEDMA_REG_LAST_READ, cur_read + 1);
ctx->last_read = cur_read;
// ctx->last_read_addr = htonl(pcilib_kmem_get_block_ba(ctx->pcilib, ctx->pages, cur_read));
@@ -421,5 +424,67 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
}
double dma_ipe_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) {
- return 0;
+ int err = 0;
+
+ ipe_dma_t *ctx = (ipe_dma_t*)vctx;
+
+ int iter;
+ size_t us = 0;
+ struct timeval start, cur;
+
+ void *buf;
+ size_t bytes, rbytes;
+
+ if ((direction == PCILIB_DMA_TO_DEVICE)||(direction == PCILIB_DMA_BIDIRECTIONAL)) return -1.;
+
+ if ((dma != PCILIB_DMA_ENGINE_INVALID)&&(dma > 1)) return -1.;
+
+ err = dma_ipe_start(vctx, 0, PCILIB_DMA_FLAGS_DEFAULT);
+ if (err) return err;
+
+ WR(IPEDMA_REG_CONTROL, 0x0);
+
+ err = pcilib_skip_dma(ctx->pcilib, 0);
+ if (err) {
+ pcilib_error("Can't start benchmark, devices continuously writes unexpected data using DMA engine");
+ return -1;
+ }
+
+ if (size%IPEDMA_PAGE_SIZE) size = (1 + size / IPEDMA_PAGE_SIZE) * IPEDMA_PAGE_SIZE;
+
+ // Allocate memory and prepare data
+ buf = malloc(size);
+ if (!buf) return -1;
+
+ for (iter = 0; iter < iterations; iter++) {
+ gettimeofday(&start, NULL);
+
+ // Starting DMA
+ WR(IPEDMA_REG_CONTROL, 0x1);
+
+ for (bytes = 0; bytes < size; bytes += rbytes) {
+ err = pcilib_read_dma(ctx->pcilib, 0, addr, size - bytes, buf + bytes, &rbytes);
+ if (err) {
+ pcilib_error("Can't read data from DMA, error %i", err);
+ return -1;
+ }
+ }
+
+ // Stopping DMA
+ WR(IPEDMA_REG_CONTROL, 0x0);
+ if (err) break;
+
+ gettimeofday(&cur, NULL);
+ us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
+
+ err = pcilib_skip_dma(ctx->pcilib, 0);
+ if (err) {
+ pcilib_error("Can't start iteration, devices continuously writes unexpected data using DMA engine");
+ break;
+ }
+ }
+
+ free(buf);
+
+ return err?-1:((1. * size * iterations * 1000000) / (1024. * 1024. * us));
}
diff --git a/dma/ipe_private.h b/dma/ipe_private.h
index 42000d1..1ae14f6 100644
--- a/dma/ipe_private.h
+++ b/dma/ipe_private.h
@@ -11,6 +11,7 @@
//#define IPEDMA_DEBUG
//#define IPEDMA_BUG_DMARD /**< No register read during DMA transfer */
+#define IPEDMA_DMA_TIMEOUT PCILIB_DMA_TIMEOUT /**< us, overrides PCILIB_DMA_TIMEOUT */
#define IPEDMA_REG_RESET 0x00
#define IPEDMA_REG_CONTROL 0x04