diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2015-02-03 15:29:35 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2015-02-03 15:29:35 +0100 |
commit | fe6a3fc5e79ed76c5f7bf84482698850aaedbae9 (patch) | |
tree | e9395f1c8f91e999c5b6ef7a22d701114fd14ea2 /dma | |
parent | 3b3f049e8dfd7314239a4f489884648b2808d735 (diff) | |
download | pcitool-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.c | 77 | ||||
-rw-r--r-- | dma/ipe_private.h | 1 |
2 files changed, 72 insertions, 6 deletions
@@ -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 |