diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-17 16:43:47 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2011-07-17 16:43:47 +0200 |
commit | 21d12d6157061bca3926607a248ccc16d6b07bd1 (patch) | |
tree | a74c3e0960725c92800399d913242e78c91e69cf | |
parent | 4fe2032eca29d7f7a0fdf23ef0f3d2c324aeeba2 (diff) | |
download | pcitool-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.gz pcitool-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.bz2 pcitool-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.xz pcitool-21d12d6157061bca3926607a248ccc16d6b07bd1.zip |
Correctly detect the tail pointer of C2S ring
-rw-r--r-- | dma/nwl.h | 2 | ||||
-rw-r--r-- | dma/nwl_engine.c | 2 | ||||
-rw-r--r-- | dma/nwl_engine_buffers.h (renamed from dma/nwl_buffers.h) | 39 | ||||
-rw-r--r-- | dma/nwl_loopback.c | 10 |
4 files changed, 19 insertions, 34 deletions
@@ -16,7 +16,7 @@ typedef struct pcilib_nwl_engine_description_s pcilib_nwl_engine_description_t; #define PCILIB_NWL_DMA_PAGES 512 // 1024 //#define DEBUG_HARDWARE - +//#define DEBUG_NWL #include "nwl_dma.h" #include "nwl_irq.h" diff --git a/dma/nwl_engine.c b/dma/nwl_engine.c index 2e7ae7e..6987045 100644 --- a/dma/nwl_engine.c +++ b/dma/nwl_engine.c @@ -14,7 +14,7 @@ #include "nwl_defines.h" -#include "nwl_buffers.h" +#include "nwl_engine_buffers.h" int dma_nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) { uint32_t val; diff --git a/dma/nwl_buffers.h b/dma/nwl_engine_buffers.h index 130c189..30385ea 100644 --- a/dma/nwl_buffers.h +++ b/dma/nwl_engine_buffers.h @@ -44,7 +44,11 @@ static int dma_nwl_compute_read_s2c_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_d pcilib_warning("Inconsistent S2C DMA Ring buffer is found (REG_DMA_ENG_NEXT_BD register value (%zu) out of range)", info->tail); return PCILIB_ERROR_INVALID_STATE; } - + +#ifdef DEBUG_NWL + printf("S2C: %lu %lu\n", info->tail, info->head); +#endif /* DEBUG_NWL */ + return 0; } @@ -69,34 +73,12 @@ static int dma_nwl_compute_read_c2s_pointers(nwl_dma_t *ctx, pcilib_nwl_engine_d return PCILIB_ERROR_INVALID_STATE; } - info->tail = info->head; - - - // Last read BD - nwl_read_register(val, ctx, base, REG_DMA_ENG_LAST_BD); - if ((val < ring_pa)||((val - ring_pa) % PCILIB_NWL_DMA_DESCRIPTOR_SIZE)) { - if (val < ring_pa) pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_DMA_ENG_LAST_BD register value (%lx) is below start of ring [%lx,%lx])", val, ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - else pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_DMA_ENG_LAST_BD register value (%zu / %u) is fractal)", val - ring_pa, PCILIB_NWL_DMA_DESCRIPTOR_SIZE); - return PCILIB_ERROR_INVALID_STATE; - } - - prev = (val - ring_pa) / PCILIB_NWL_DMA_DESCRIPTOR_SIZE; - if (prev >= PCILIB_NWL_DMA_PAGES) { - pcilib_warning("Inconsistent C2S DMA Ring buffer is found (REG_DMA_ENG_LAST_BD register value (%zu) out of range)", prev); - return PCILIB_ERROR_INVALID_STATE; - } - -prev_buffer: - val = NWL_RING_GET(ring + prev * PCILIB_NWL_DMA_DESCRIPTOR_SIZE, DMA_BD_BUFL_STATUS_OFFSET)&DMA_BD_STATUS_MASK; + info->tail = info->head + 1; + if (info->tail == PCILIB_NWL_DMA_PAGES) info->tail = 0; - if (val & (DMA_BD_ERROR_MASK|DMA_BD_COMP_MASK)) { - info->tail = prev; - - if (prev > 0) prev -= 1; - else prev = PCILIB_NWL_DMA_PAGES - 1; - - if (prev != info->head) goto prev_buffer; - } +#ifdef DEBUG_NWL + printf("C2S: %lu %lu\n", info->tail, info->head); +#endif /* DEBUG_NWL */ return 0; } @@ -137,6 +119,7 @@ static int dma_nwl_allocate_engine_buffers(nwl_dma_t *ctx, pcilib_nwl_engine_des reuse_ring = pcilib_kmem_is_reused(ctx->pcilib, ring); reuse_pages = pcilib_kmem_is_reused(ctx->pcilib, pages); + if (!info->preserve) { if (reuse_ring == reuse_pages) { if (reuse_ring & PCILIB_KMEM_REUSE_PARTIAL) pcilib_warning("Inconsistent DMA buffers are found (only part of required buffers is available), reinitializing..."); diff --git a/dma/nwl_loopback.c b/dma/nwl_loopback.c index 3c2c124..de17962 100644 --- a/dma/nwl_loopback.c +++ b/dma/nwl_loopback.c @@ -16,7 +16,8 @@ int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, size_t packet_size) { uint32_t val; - // Re-initializing always + ctx->loopback_started = 1; + dma_nwl_stop_loopback(ctx); val = packet_size; nwl_write_register(val, ctx, ctx->base_addr, PKT_SIZE_ADDRESS); @@ -24,17 +25,16 @@ int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, si switch (direction) { case PCILIB_DMA_BIDIRECTIONAL: val = LOOPBACK; + nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); break; case PCILIB_DMA_TO_DEVICE: return -1; case PCILIB_DMA_FROM_DEVICE: val = PKTGENR; + nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); break; } - nwl_write_register(val, ctx, ctx->base_addr, TX_CONFIG_ADDRESS); - nwl_write_register(val, ctx, ctx->base_addr, RX_CONFIG_ADDRESS); - ctx->loopback_started = 1; return 0; @@ -42,6 +42,8 @@ int dma_nwl_start_loopback(nwl_dma_t *ctx, pcilib_dma_direction_t direction, si int dma_nwl_stop_loopback(nwl_dma_t *ctx) { uint32_t val = 0; + + if (!ctx->loopback_started) return 0; /* Stop in any case, otherwise we can have problems in benchmark due to engine initialized in previous run, and benchmark is only actual usage. |