Browse Source

Support streaming mode in IPEDMA

Suren A. Chilingaryan 9 years ago
parent
commit
36385f1e83
3 changed files with 28 additions and 2 deletions
  1. 15 1
      dma/ipe.c
  2. 5 1
      dma/ipe_private.h
  3. 8 0
      docs/IPEHARDWARE

+ 15 - 1
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);

+ 5 - 1
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); }

+ 8 - 0
docs/IPEHARDWARE

@@ -0,0 +1,8 @@
+IPEDMA
+======
+ - Normally, we are using register 0x5C to get number of buffers configured in the hardware
+ and check if it is consistent with number of allocated buffers. However, in streaming mode
+ this does not work at the moment. After writting the buffers, the hardware forgets them 
+ and only stores the current queue of free buffers. Currently, the check is disabled in the
+ streaming mode. Can we handle it somehow?
+