summaryrefslogtreecommitdiffstats
path: root/dma
diff options
context:
space:
mode:
Diffstat (limited to 'dma')
-rw-r--r--dma/ipe.c16
-rw-r--r--dma/ipe_private.h6
2 files changed, 20 insertions, 2 deletions
diff --git a/dma/ipe.c b/dma/ipe.c
index a9ecc90..953de09 100644
--- a/dma/ipe.c
+++ b/dma/ipe.c
@@ -111,10 +111,12 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
else if ((reuse_desc & PCILIB_KMEM_REUSE_HARDWARE) == 0) pcilib_warning("Lost DMA buffers are found (missing HW reference), reinitializing...");
else {
#ifndef IPEDMA_BUG_DMARD
+# ifndef IPEDMA_STREAMING_MODE
RD(IPEDMA_REG_PAGE_COUNT, value);
if (value != IPEDMA_DMA_PAGES) pcilib_warning("Inconsistent DMA buffers are found (Number of allocated buffers (%lu) does not match current request (%lu)), reinitializing...", value + 1, IPEDMA_DMA_PAGES);
else
+# endif /* IPEDMA_STREAMING_MODE */
#endif /* IPEDMA_BUG_DMARD */
preserve = 1;
}
@@ -501,9 +503,21 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
ret = cb(cbattr, packet_flags, ctx->page_size, buf);
if (ret < 0) return -ret;
- // We don't need this because hardwaredoes not intend to read anything from the memory
+ // We don't need this because hardware does not intend to read anything from the memory
// pcilib_kmem_sync_block(ctx->dmactx.pcilib, ctx->pages, PCILIB_KMEM_SYNC_TODEVICE, cur_read);
+ // Return buffer into the DMA pool when processed
+#ifdef IPEDMA_STREAMING_MODE
+ uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, cur_read);
+ WR(IPEDMA_REG_PAGE_ADDR, buf_ba);
+# ifdef IPEDMA_STREAMING_CHECKS
+ pcilib_register_value_t streaming_status;
+ RD(IPEDMA_REG_STREAMING_STATUS, streaming_status);
+ if (streaming_status)
+ pcilib_error("Invalid status (0x%lx) adding a DMA buffer into the queue", streaming_status);
+# endif /* IPEDMA_STREAMING_MODE */
+#endif /* IPEDMA_STREAMING_MODE */
+
// Numbered from 1
#ifdef IPEDMA_BUG_LAST_READ
WR(IPEDMA_REG_LAST_READ, cur_read?cur_read:IPEDMA_DMA_PAGES);
diff --git a/dma/ipe_private.h b/dma/ipe_private.h
index 5cfb10b..249286d 100644
--- a/dma/ipe_private.h
+++ b/dma/ipe_private.h
@@ -8,6 +8,8 @@
#define IPEDMA_MAX_TLP_SIZE 256 /**< Defines maximum TLP in bytes supported by device */
//#define IPEDMA_TLP_SIZE 128 /**< If set, enforces the specified TLP size */
+#define IPEDMA_STREAMING_MODE /**< Enables streaming DMA operation mode instead of ring-buffer, the page is written once and forgotten and need to be pushed in queue again */
+#define IPEDMA_STREAMING_CHECKS /**< Enables status checks in streaming mode (it will cause performance penalty) */
#define IPEDMA_PAGE_SIZE 4096
#define IPEDMA_DMA_PAGES 1024 /**< number of DMA pages in the ring buffer to allocate */
#define IPEDMA_DMA_PROGRESS_THRESHOLD 1 /**< how many pages the DMA engine should fill before reporting progress */
@@ -31,9 +33,11 @@
#define IPEDMA_REG_TLP_COUNT 0x10
#define IPEDMA_REG_PAGE_ADDR 0x50
#define IPEDMA_REG_UPDATE_ADDR 0x54
-#define IPEDMA_REG_LAST_READ 0x58
+#define IPEDMA_REG_LAST_READ 0x58 /**< In streaming mode, we can use it freely to track current status */
#define IPEDMA_REG_PAGE_COUNT 0x5C
#define IPEDMA_REG_UPDATE_THRESHOLD 0x60
+#define IPEDMA_REG_STREAMING_STATUS 0x68
+
#define WR(addr, value) { *(uint32_t*)(ctx->base_addr + addr) = value; }
#define RD(addr, value) { value = *(uint32_t*)(ctx->base_addr + addr); }