summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-17 16:43:47 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-07-17 16:43:47 +0200
commit21d12d6157061bca3926607a248ccc16d6b07bd1 (patch)
treea74c3e0960725c92800399d913242e78c91e69cf
parent4fe2032eca29d7f7a0fdf23ef0f3d2c324aeeba2 (diff)
downloadipecamera-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.gz
ipecamera-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.bz2
ipecamera-21d12d6157061bca3926607a248ccc16d6b07bd1.tar.xz
ipecamera-21d12d6157061bca3926607a248ccc16d6b07bd1.zip
Correctly detect the tail pointer of C2S ring
-rw-r--r--dma/nwl.h2
-rw-r--r--dma/nwl_engine.c2
-rw-r--r--dma/nwl_engine_buffers.h (renamed from dma/nwl_buffers.h)39
-rw-r--r--dma/nwl_loopback.c10
4 files changed, 19 insertions, 34 deletions
diff --git a/dma/nwl.h b/dma/nwl.h
index 8197bf9..30eff9a 100644
--- a/dma/nwl.h
+++ b/dma/nwl.h
@@ -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.