From 61d520876b16acdd97f32467e2af5bd531a516af Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Thu, 6 Aug 2015 16:45:00 +0200 Subject: In IPEDMA streaming mode put aside a single empty buffer to distinguish between completely empty and full states of kernel ring buffer --- dma/ipe.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'dma/ipe.c') diff --git a/dma/ipe.c b/dma/ipe.c index 2ed3e05..3e46cb3 100644 --- a/dma/ipe.c +++ b/dma/ipe.c @@ -71,7 +71,7 @@ void dma_ipe_free(pcilib_dma_context_t *vctx) { int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) { - size_t i; + size_t i, num_pages; ipe_dma_t *ctx = (ipe_dma_t*)vctx; @@ -203,7 +203,13 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm // Instructing DMA engine that writting should start from the first DMA page *last_written_addr_ptr = 0; - for (i = 0; i < IPEDMA_DMA_PAGES; i++) { + // In ring buffer mode, the hardware taking care to preserve an empty buffer to help distinguish between + // completely empty and completely full cases. In streaming mode, it is our responsibility to track this + // information. Therefore, we always keep the last buffer free + num_pages = IPEDMA_DMA_PAGES; + if (ctx->streaming) num_pages--; + + for (i = 0; i < num_pages; i++) { uintptr_t bus_addr_check, bus_addr = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, pages, i); WR(IPEDMA_REG_PAGE_ADDR, bus_addr); if (bus_addr%4096) printf("Bad address %lu: %lx\n", i, bus_addr); @@ -496,7 +502,12 @@ int dma_ipe_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin // Return buffer into the DMA pool when processed if (ctx->streaming) { - uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, cur_read); + size_t last_free; + // We always keep 1 buffer free to distinguish between completely full and empty cases + if (cur_read) last_free = cur_read - 1; + else last_free = IPEDMA_DMA_PAGES - 1; + + uintptr_t buf_ba = pcilib_kmem_get_block_ba(ctx->dmactx.pcilib, ctx->pages, last_free); WR(IPEDMA_REG_PAGE_ADDR, buf_ba); # ifdef IPEDMA_STREAMING_CHECKS pcilib_register_value_t streaming_status; -- cgit v1.2.3