Selaa lähdekoodia

Reorganization of NWL engine, step 1

Suren A. Chilingaryan 13 vuotta sitten
vanhempi
commit
93bb2a3a6c
5 muutettua tiedostoa jossa 176 lisäystä ja 128 poistoa
  1. 5 0
      cli.c
  2. 166 89
      dma/nwl.c
  3. 2 0
      dma/nwl.h
  4. 0 39
      dma/nwl_buffers.h
  5. 3 0
      dma/nwl_irq.c

+ 5 - 0
cli.c

@@ -127,6 +127,11 @@ void Usage(int argc, char *argv[], const char *format, ...) {
 "	--reset			- Reset board\n"
 "	--help			- Help message\n"
 "\n"
+"  DMA Modes:\n"
+"	--start-dma <num>	- Start specified DMA engine\n"
+"	--stop-dma [num]	- Stop specified engine or DMA subsystem\n"
+"	--wait-irq <source>	- Wait for IRQ\n"
+"\n"
 "  Addressing:\n"
 "	-d <device>		- FPGA device (/dev/fpga0)\n"
 "	-m <model>		- Memory model (autodetected)\n"

+ 166 - 89
dma/nwl.c

@@ -28,7 +28,7 @@
 #define PCILIB_NWL_DMA_PAGES			512 // 1024
 
 
-static int nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
+static int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
     uint32_t val;
     
     info->base_addr = base;
@@ -60,40 +60,32 @@ static int nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_
     }
     
     info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT;
+
+    info->base_addr = addr;
     
     return 0;
 }
 
 
-int nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
+int dma_nwl_start_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
+    int err;
     uint32_t val;
+    uint32_t ring_pa;
     struct timeval start, cur;
-    
+
     pcilib_nwl_engine_description_t *info = ctx->engines + dma;
     char *base = ctx->engines[dma].base_addr;
 
-    return 0;
-    if (info->desc.addr == NWL_XRAWDATA_ENGINE) {
-	    // Stop Generators
-	nwl_read_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-	val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-	nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-
-	nwl_read_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-	val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-	nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
-	    // Skip everything in read queue (could be we need to start and skip as well)
-	if (info->started) pcilib_skip_dma(ctx->pcilib, dma);
-    }
+    if (info->started) return 0;
+
+	// Disable IRQs
+    err = dma_nwl_disable_engine_irq(ctx, dma);
+    if (err) return err;
 
-	// Disable IRQ
-    nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
-    val &= ~(DMA_ENG_INT_ENABLE);
+	// Disable Engine & Reseting 
+    val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET;
     nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
 
-	// Reseting 
-    val = DMA_ENG_DISABLE|DMA_ENG_USER_RESET; nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
     gettimeofday(&start, NULL);
     do {
 	nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
@@ -105,7 +97,9 @@ int nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
 	return PCILIB_ERROR_TIMEOUT;
     }
 
-    val = DMA_ENG_RESET; nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
+    val = DMA_ENG_RESET; 
+    nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
+    
     gettimeofday(&start, NULL);
     do {
 	nwl_read_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
@@ -122,7 +116,75 @@ int nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
 	val |= DMA_ENG_ALLINT_MASK;
 	nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
     }
+
+    err = dma_nwl_start(ctx);
+    if (err) return err;
+    
+    err = dma_nwl_allocate_engine_buffers(ctx, info);
+    if (err) return err;
+    
+    ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
+    nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD);
+    nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
+
+    __sync_synchronize();
+
+    nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+    val |= (DMA_ENG_ENABLE);
+    nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
+
+    __sync_synchronize();
+
+#ifdef NWL_GENERATE_DMA_IRQ
+    nwl_dma_enable_engine_irq(ctx, dma);
+#endif /* NWL_GENERATE_DMA_IRQ */
+
+    if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) {
+	ring_pa += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
+    	nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
+
+	info->tail = 0;
+	info->head = (info->ring_size - 1);
+    } else {
+	info->tail = 0;
+	info->head = 0;
+    }
+    
+    info->started = 1;
     
+    return 0;
+}
+
+
+int dma_nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
+    int err;
+    uint32_t val;
+    uint32_t ring_pa;
+    struct timeval start, cur;
+    
+    pcilib_nwl_engine_description_t *info = ctx->engines + dma;
+    char *base = ctx->engines[dma].base_addr;
+
+    info->started = 0;
+
+    err = dma_nwl_disable_engine_irq(ctx, dma);
+    if (err) return err;
+
+    val = DMA_ENG_DISABLE; 
+    nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
+
+    if (info->ring) {
+	ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
+	nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD);
+	nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
+    }
+
+	// Acknowledge asserted engine interrupts    
+    if (val & DMA_ENG_INT_ACTIVE_MASK) {
+	val |= DMA_ENG_ALLINT_MASK;
+	nwl_write_register(val, ctx, base, REG_DMA_ENG_CTRL_STATUS);
+    }
+
 	// Clean buffers
     if (info->ring) {
 	pcilib_free_kernel_memory(ctx->pcilib, info->ring);
@@ -133,12 +195,80 @@ int nwl_stop_engine(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
 	pcilib_free_kernel_memory(ctx->pcilib, info->pages);
 	info->pages = NULL;
     }
+
+
+
+    return 0;
+}
+
+
+int dma_nwl_start_loopback(nwl_dma_t *ctx,  pcilib_dma_direction_t direction, size_t packet_size) {
+    uint32_t val;
     
-    info->started = 0;
+    val = packet_size;
+    nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS);
+
+    switch (direction) {
+      case PCILIB_DMA_BIDIRECTIONAL:
+	val = LOOPBACK;
+	break;
+      case PCILIB_DMA_TO_DEVICE:
+	return -1;
+      case PCILIB_DMA_FROM_DEVICE:
+        val = PKTGENR;
+	break;
+    }
+
+    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
+    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
+    
+    return 0;
+}
+
+int dma_nwl_stop_loopback(nwl_dma_t *ctx) {
+    uint32_t val;
+
+    val = 0;
+    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
+    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
+    
+    return 0;
+}
+
+
+int dma_nwl_start(nwl_dma_t *ctx) {
+    if (ctx->started) return 0;
+    
+#ifdef NWL_GENERATE_DMA_IRQ
+    nwl_dma_enable_irq(ctx, PCILIB_DMA_IRQ);
+#endif /* NWL_GENERATE_DMA_IRQ */
+
+    ctx->started = 1;
 
     return 0;
 }
 
+int dma_nwl_stop(nwl_dma_t *ctx) {
+    int err;
+
+    pcilib_dma_engine_t i;
+    
+    ctx->started = 0;
+    
+    err = dma_nwl_disable_irq(ctx);
+    if (err) return err;
+    
+    err = dma_nwl_stop_loopback(ctx);
+    if (err) return err;
+    
+    for (i = 0; i < ctx->n_engines; i++) {
+	err = nwl_stop_engine(ctx, i);
+	if (err) return err;
+    }
+    
+    return 0;
+}
+
 
 pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
     int i;
@@ -152,8 +282,8 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
     if (ctx) {
 	memset(ctx, 0, sizeof(nwl_dma_t));
 	ctx->pcilib = pcilib;
-	pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
 
+	pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
 	if (dma_bank == PCILIB_REGISTER_BANK_INVALID) {
 	    free(ctx);
 	    pcilib_error("DMA Register Bank could not be found");
@@ -163,23 +293,16 @@ pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
 	ctx->dma_bank = model_info->banks + dma_bank;
 	ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr);
 
-        val = 0;
-	nwl_read_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-	nwl_read_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
 	for (i = 0, n_engines = 0; i < 2 * PCILIB_MAX_DMA_ENGINES; i++) {
 	    char *addr = ctx->base_addr + DMA_OFFSET + i * DMA_ENGINE_PER_SIZE;
 
 	    memset(ctx->engines + n_engines, 0, sizeof(pcilib_nwl_engine_description_t));
 
 	    err = nwl_read_engine_config(ctx, ctx->engines + n_engines, addr);
-	    if (!err) err = nwl_stop_engine(ctx, n_engines);
-	    if (!err) {
-		ctx->engines[n_engines].base_addr = addr;
-		pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines));
-		++n_engines;
-	    }
+	    if (err) continue;
 	    
+	    pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines));
+	    ++n_engines;
 	}
 	pcilib_set_dma_engine_description(pcilib, n_engines, NULL);
 	
@@ -199,7 +322,8 @@ void  dma_nwl_free(pcilib_dma_context_t *vctx) {
     pcilib_dma_engine_t i;
     nwl_dma_t *ctx = (nwl_dma_t*)vctx;
     if (ctx) {
-	for (i = 0; i < ctx->n_engines; i++) nwl_stop_engine(vctx, i);
+	for (i = 0; i < ctx->n_engines; i++) dma_nwl_stop_engine(ctx, i);
+	dma_nwl_stop(ctx);
 	free(ctx);
     }
 }
@@ -225,7 +349,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma,
 
     pcilib_nwl_engine_description_t *info = ctx->engines + dma;
 
-    err = dma_nwl_start(ctx, info);
+    err = dma_nwl_start_engine(ctx, dma);
     if (err) return err;
 
     if (data) {
@@ -271,7 +395,7 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
 
     pcilib_nwl_engine_description_t *info = ctx->engines + dma;
 
-    err = dma_nwl_start(ctx, info);
+    err = dma_nwl_start_engine(ctx, dma);
     if (err) return err;
 
     do {
@@ -292,15 +416,13 @@ int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uin
 	dma_nwl_return_buffer(ctx, info);
 	
 	res += bufsize;
-	
-//	printf("%i %i %i (%li)\n", ret, res, eop, size);
+
     } while (ret);
     
     return 0;
 }
 
 
-
 double dma_nwl_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) {
     int i;
     int res;
@@ -324,25 +446,8 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
     if (size%sizeof(uint32_t)) size = 1 + size / sizeof(uint32_t);
     else size /= sizeof(uint32_t);
 
-
 	// Stop Generators and drain old data
-    nwl_read_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-    val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-
-    nwl_read_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-    val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
-/*
-    nwl_stop_engine(ctx, readid);
-    nwl_stop_engine(ctx, writeid);
-
-    err = dma_nwl_start(ctx, ctx->engines + readid);
-    if (err) return -1;
-    err = dma_nwl_start(ctx, ctx->engines + writeid);
-    if (err) return -1;
-*/
+    dma_nwl_stop_loopback(ctx);
 
     __sync_synchronize();
 
@@ -352,24 +457,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
     dma_nwl_enable_engine_irq(ctx, readid);
 #endif /* NWL_GENERATE_DMA_IRQ */
     
-	// Set size and required mode
-    val = size * sizeof(uint32_t);
-    nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS);
-
-    switch (direction) {
-      case PCILIB_DMA_BIDIRECTIONAL:
-	val = LOOPBACK;
-	break;
-      case PCILIB_DMA_TO_DEVICE:
-	return -1;
-      case PCILIB_DMA_FROM_DEVICE:
-        val = PKTGENR;
-	break;
-    }
-
-    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-
+    dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t));
 
 	// Allocate memory and prepare data
     buf = malloc(size * sizeof(uint32_t));
@@ -384,8 +472,6 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
 
 	// Benchmark
     for (i = 0; i < iterations; i++) {
-//	printf("Iteration: %i\n", i);
-
         gettimeofday(&start, NULL);
 	if (direction&PCILIB_DMA_TO_DEVICE) {
 	    memcpy(buf, cmp, size * sizeof(uint32_t));
@@ -403,9 +489,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
         gettimeofday(&cur, NULL);
 	us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec));
 
-
 	if ((err)||(bytes != size * sizeof(uint32_t))) {
-//	     printf("RF: %li %li\n", bytes, size * 4);
 	     error = "Read failed";
 	     break;
 	}
@@ -424,14 +508,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm
     dma_nwl_disable_irq(ctx);
 #endif /* NWL_GENERATE_DMA_IRQ */
 
-	// Stop Generators and drain data if necessary
-    nwl_read_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-    val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-    nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS);
-
-    nwl_read_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
-    val = ~(LOOPBACK|PKTCHKR|PKTGENR);
-    nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS);
+    dma_nwl_stop_loopback(ctx);
 
     __sync_synchronize();
     

+ 2 - 0
dma/nwl.h

@@ -29,6 +29,8 @@ struct nwl_dma_s {
     char *base_addr;
     
     pcilib_irq_type_t irq_enabled;
+
+    int started;
     
     pcilib_dma_engine_t n_engines;
     pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1];

+ 0 - 39
dma/nwl_buffers.h

@@ -62,45 +62,6 @@ int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_descriptio
 }
 
 
-static int dma_nwl_start(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info) {
-    int err;
-    uint32_t ring_pa;
-    uint32_t val;
-
-    if (info->started) return 0;
-    
-    err = dma_nwl_allocate_engine_buffers(ctx, info);
-    if (err) return err;
-    
-    ring_pa = pcilib_kmem_get_pa(ctx->pcilib, info->ring);
-    nwl_write_register(ring_pa, ctx, info->base_addr, REG_DMA_ENG_NEXT_BD);
-    nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
-
-    __sync_synchronize();
-
-    nwl_read_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
-    val |= (DMA_ENG_ENABLE);
-    nwl_write_register(val, ctx, info->base_addr, REG_DMA_ENG_CTRL_STATUS);
-
-    __sync_synchronize();
-
-    if (info->desc.direction == PCILIB_DMA_FROM_DEVICE) {
-	ring_pa += (info->ring_size - 1) * PCILIB_NWL_DMA_DESCRIPTOR_SIZE;
-    	nwl_write_register(ring_pa, ctx, info->base_addr, REG_SW_NEXT_BD);
-//	nwl_read_register(val, ctx, info->base_addr, 0x18);
-
-	info->tail = 0;
-	info->head = (info->ring_size - 1);
-    } else {
-	info->tail = 0;
-	info->head = 0;
-    }
-    
-    info->started = 1;
-    
-    return 0;
-}
-
 static size_t dma_nwl_clean_buffers(nwl_dma_t * ctx, pcilib_nwl_engine_description_t *info) {
     size_t res = 0;
     uint32_t status, control;

+ 3 - 0
dma/nwl_irq.c

@@ -66,3 +66,6 @@ int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) {
 
     return 0;
 }
+
+
+// ACK