From 493958c9cf11eaa25251d91e9ecab9a28bd6d68f Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Tue, 12 Jul 2011 14:39:06 +0200 Subject: Provide IRQ enable/disable call --- dma/nwl.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ dma/nwl.h | 5 ++-- dma/nwl_dma.h | 7 ++++-- dma/nwl_irq.c | 42 ++++++++++++++++++++++++++++--- dma/nwl_irq.h | 5 ++-- 5 files changed, 121 insertions(+), 18 deletions(-) (limited to 'dma') diff --git a/dma/nwl.c b/dma/nwl.c index 6c3079a..bca0c5c 100644 --- a/dma/nwl.c +++ b/dma/nwl.c @@ -240,7 +240,7 @@ int dma_nwl_start(nwl_dma_t *ctx) { if (ctx->started) return 0; #ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_enable_irq(ctx, PCILIB_DMA_IRQ); + dma_nwl_enable_irq(ctx, PCILIB_DMA_IRQ, 0); #endif /* NWL_GENERATE_DMA_IRQ */ ctx->started = 1; @@ -255,7 +255,7 @@ int dma_nwl_stop(nwl_dma_t *ctx) { ctx->started = 0; - err = dma_nwl_disable_irq(ctx); + err = dma_nwl_free_irq(ctx); if (err) return err; err = dma_nwl_stop_loopback(ctx); @@ -355,7 +355,7 @@ int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, if (data) { for (pos = 0; pos < size; pos += info->page_size) { int block_size = min2(size - pos, info->page_size); - + bufnum = dma_nwl_get_next_buffer(ctx, info, 1, timeout); if (bufnum == PCILIB_DMA_BUFFER_INVALID) { if (written) *written = pos; @@ -431,6 +431,7 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm uint32_t val; uint32_t *buf, *cmp; const char *error = NULL; +// pcilib_register_value_t regval; size_t us = 0; struct timeval start, cur; @@ -446,9 +447,12 @@ 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); + // Not supported + if (direction == PCILIB_DMA_TO_DEVICE) return -1.; + // Stop Generators and drain old data dma_nwl_stop_loopback(ctx); - dma_nwl_stop_engine(ctx, readid); // DS: replace with something better +// dma_nwl_stop_engine(ctx, readid); // DS: replace with something better __sync_synchronize(); @@ -456,15 +460,26 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm #ifdef NWL_GENERATE_DMA_IRQ dma_nwl_enable_engine_irq(ctx, readid); + dma_nwl_enable_engine_irq(ctx, writeid); #endif /* NWL_GENERATE_DMA_IRQ */ + dma_nwl_start_loopback(ctx, direction, size * sizeof(uint32_t)); /* + printf("Packet size: %li\n", size * sizeof(uint32_t)); + pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", ®val); + printf("Count write: %lx\n", regval); + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); printf("Read DMA control: %lx\n", val); nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS); printf("Write DMA control: %lx\n", val); + + nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); + printf("Pointer1: %lx\n", val); + nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); + printf("Pointer2: %lx\n", val); */ // Allocate memory and prepare data @@ -486,11 +501,27 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm err = pcilib_write_dma(ctx->pcilib, writeid, addr, size * sizeof(uint32_t), buf, &bytes); if ((err)||(bytes != size * sizeof(uint32_t))) { - printf("%i %lu write\n", err, bytes); error = "Write failed"; break; } } +/* + printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1w_counter", ®val)); + printf("Count write (%i of %i): %lx\n", i, iterations, regval); + + printf("RegRead: %i\n",pcilib_read_register(ctx->pcilib, NULL, "dma1r_counter", ®val)); + printf("Count read (%i of %i): %lx\n", i, iterations, regval); + + + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_COMP_BYTES); + printf("Compl Bytes (read): %lx\n", val); + + nwl_read_register(val, ctx, write_base, REG_DMA_ENG_COMP_BYTES); + printf("Compl Bytes (write): %lx\n", val); + + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); + printf("Read DMA control (after write): %lx\n", val); +*/ /* nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); printf("Read DMA control (after write): %lx\n", val); @@ -504,7 +535,23 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm us += ((cur.tv_sec - start.tv_sec)*1000000 + (cur.tv_usec - start.tv_usec)); if ((err)||(bytes != size * sizeof(uint32_t))) { - printf("%i %lu read\n", err, bytes); +/* + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_CTRL_STATUS); + printf("Read DMA control: %lx\n", val); + nwl_read_register(val, ctx, write_base, REG_DMA_ENG_CTRL_STATUS); + printf("Write DMA control: %lx\n", val); + nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); + printf("After Pointer wr1: %lx\n", val); + nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); + printf("After Pointer wr2: %lx\n", val); + pcilib_read_register(ctx->pcilib, NULL, "end_address", ®val); + printf("End address: %lx\n", regval); + + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD); + printf("After Pointer read1: %lx\n", val); + nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD); + printf("After Pointer read2: %lx\n", val); +*/ error = "Read failed"; break; } @@ -512,16 +559,33 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm if (direction == PCILIB_DMA_BIDIRECTIONAL) { res = memcmp(buf, cmp, size * sizeof(uint32_t)); if (res) { - puts("verify"); error = "Written and read values does not match"; break; } } } + + if (error) { + pcilib_warning("%s at iteration %i, error: %i, bytes: %zu", error, i, err, bytes); + } + +/* + puts("Finished..."); + nwl_read_register(val, ctx, read_base, REG_DMA_ENG_NEXT_BD); + printf("After Pointer read1: %lx\n", val); + nwl_read_register(val, ctx, read_base, REG_SW_NEXT_BD); + printf("After Pointer read2: %lx\n", val); + + nwl_read_register(val, ctx, write_base, REG_DMA_ENG_NEXT_BD); + printf("After Pointer wr1: %lx\n", val); + nwl_read_register(val, ctx, write_base, REG_SW_NEXT_BD); + printf("After Pointer wr2: %lx\n", val); +*/ #ifdef NWL_GENERATE_DMA_IRQ - dma_nwl_disable_irq(ctx); + dma_nwl_disable_engine_irq(ctx, writeid); + dma_nwl_disable_engine_irq(ctx, readid); #endif /* NWL_GENERATE_DMA_IRQ */ dma_nwl_stop_loopback(ctx); diff --git a/dma/nwl.h b/dma/nwl.h index 1ee6f5d..4e15418 100644 --- a/dma/nwl.h +++ b/dma/nwl.h @@ -28,9 +28,10 @@ struct nwl_dma_s { pcilib_register_bank_description_t *dma_bank; char *base_addr; - + + int irq_init; /**< indicates that IRQ subsystem is initialized (detecting which types should be preserverd) */ pcilib_irq_type_t irq_enabled; /**< indicates that IRQs are enabled */ - int irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */ + pcilib_irq_type_t irq_preserve; /**< indicates that IRQs should not be disabled during clean-up */ int started; /**< indicates that DMA subsystem is initialized and DMA engine can start */ pcilib_dma_engine_t n_engines; diff --git a/dma/nwl_dma.h b/dma/nwl_dma.h index 5ba9b18..70b9d97 100644 --- a/dma/nwl_dma.h +++ b/dma/nwl_dma.h @@ -11,6 +11,9 @@ typedef struct nwl_dma_s nwl_dma_t; pcilib_dma_context_t *dma_nwl_init(pcilib_t *ctx); void dma_nwl_free(pcilib_dma_context_t *vctx); +int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags); +int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags); + int dma_nwl_write_fragment(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, void *data, size_t *written); int dma_nwl_stream_read(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, uintptr_t addr, size_t size, pcilib_dma_flags_t flags, pcilib_timeout_t timeout, pcilib_dma_callback_t cb, void *cbattr); 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); @@ -20,8 +23,8 @@ double dma_nwl_benchmark(pcilib_dma_context_t *vctx, pcilib_dma_engine_addr_t dm pcilib_dma_api_description_t nwl_dma_api = { dma_nwl_init, dma_nwl_free, - NULL, - NULL, + dma_nwl_enable_irq, + dma_nwl_disable_irq, NULL, NULL, dma_nwl_write_fragment, diff --git a/dma/nwl_irq.c b/dma/nwl_irq.c index 51705ff..04ac908 100644 --- a/dma/nwl_irq.c +++ b/dma/nwl_irq.c @@ -13,12 +13,39 @@ #include "nwl.h" #include "nwl_defines.h" -int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type) { +int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val) { + if (val&(DMA_INT_ENABLE|DMA_USER_INT_ENABLE)) { + if (val&DMA_INT_ENABLE) ctx->irq_preserve |= PCILIB_DMA_IRQ; + if (val&DMA_USER_INT_ENABLE) ctx->irq_preserve |= PCILIB_EVENT_IRQ; + } + + ctx->irq_init = 1; + return 0; +} + +int dma_nwl_free_irq(nwl_dma_t *ctx) { + if (ctx->irq_init) { + dma_nwl_disable_irq((pcilib_dma_context_t*)ctx, 0); + if (ctx->irq_preserve) dma_nwl_enable_irq((pcilib_dma_context_t*)ctx, ctx->irq_preserve, 0); + ctx->irq_enabled = 0; + ctx->irq_init = 0; + } + return 0; +} + +int dma_nwl_enable_irq(pcilib_dma_context_t *vctx, pcilib_irq_type_t type, pcilib_dma_flags_t flags) { uint32_t val; + nwl_dma_t *ctx = (nwl_dma_t*)vctx; - if (ctx->irq_enabled == type) return 0; + if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->irq_preserve |= type; + if (ctx->irq_enabled == type) return 0; + + type |= ctx->irq_enabled; + nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); + if (!ctx->irq_init) dma_nwl_init_irq(ctx, val); + val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE); nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); @@ -33,22 +60,28 @@ int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type) { return 0; } -int dma_nwl_disable_irq(nwl_dma_t *ctx) { + +int dma_nwl_disable_irq(pcilib_dma_context_t *vctx, pcilib_dma_flags_t flags) { uint32_t val; + nwl_dma_t *ctx = (nwl_dma_t*)vctx; ctx->irq_enabled = 0; nwl_read_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); + if (!ctx->irq_init) dma_nwl_init_irq(ctx, val); val &= ~(DMA_INT_ENABLE|DMA_USER_INT_ENABLE); nwl_write_register(val, ctx, ctx->base_addr, REG_DMA_CTRL_STATUS); + if (flags&PCILIB_DMA_FLAG_PERMANENT) ctx->irq_preserve = 0; + return 0; } + int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { uint32_t val; - dma_nwl_enable_irq(ctx, ctx->irq_enabled|PCILIB_DMA_IRQ); + dma_nwl_enable_irq(ctx, ctx->irq_enabled|PCILIB_DMA_IRQ, 0); nwl_read_register(val, ctx, ctx->engines[dma].base_addr, REG_DMA_ENG_CTRL_STATUS); val |= (DMA_ENG_INT_ENABLE); @@ -68,4 +101,5 @@ int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma) { } + // ACK diff --git a/dma/nwl_irq.h b/dma/nwl_irq.h index 685d74c..811b632 100644 --- a/dma/nwl_irq.h +++ b/dma/nwl_irq.h @@ -1,8 +1,9 @@ #ifndef _PCILIB_NWL_IRQ_H #define _PCILIB_NWL_IRQ_H -int dma_nwl_enable_irq(nwl_dma_t *ctx, pcilib_irq_type_t type); -int dma_nwl_disable_irq(nwl_dma_t *ctx); +int dma_nwl_init_irq(nwl_dma_t *ctx, uint32_t val); +int dma_nwl_free_irq(nwl_dma_t *ctx); + int dma_nwl_enable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma); int dma_nwl_disable_engine_irq(nwl_dma_t *ctx, pcilib_dma_engine_t dma); -- cgit v1.2.3