summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2013-06-20 19:15:55 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2013-06-20 19:15:55 +0200
commit7ec4581ad37b88bbb300ac00850603433a8cdfe9 (patch)
tree6c78a5a4f876469226b54a9f9e4d7b749bebb3f9
parent0444091c36134f176738393b659ea60e09dda423 (diff)
downloadpcitool-7ec4581ad37b88bbb300ac00850603433a8cdfe9.tar.gz
pcitool-7ec4581ad37b88bbb300ac00850603433a8cdfe9.tar.bz2
pcitool-7ec4581ad37b88bbb300ac00850603433a8cdfe9.tar.xz
pcitool-7ec4581ad37b88bbb300ac00850603433a8cdfe9.zip
Multipage DMA tests for Xilinx
-rw-r--r--.bzrignore2
-rw-r--r--apps/CMakeLists.txt3
-rwxr-xr-xapps/load.sh3
-rw-r--r--apps/xilinx2.c179
-rw-r--r--driver/kmem.c19
-rw-r--r--ipecamera/ipecamera.c3
-rw-r--r--ipecamera/model.h2
7 files changed, 202 insertions, 9 deletions
diff --git a/.bzrignore b/.bzrignore
index f584400..17e5a11 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -19,3 +19,5 @@ Makefile
*.so.*
install_manifest.txt
./xilinx
+apps/xilinx
+apps/xilinx2
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 2f882a3..80a506f 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -6,3 +6,6 @@ link_directories(${UFODECODE_LIBRARY_DIRS})
add_executable(xilinx xilinx.c)
target_link_libraries(xilinx pcilib rt)
+
+add_executable(xilinx2 xilinx2.c)
+target_link_libraries(xilinx2 pcilib rt)
diff --git a/apps/load.sh b/apps/load.sh
new file mode 100755
index 0000000..6456c63
--- /dev/null
+++ b/apps/load.sh
@@ -0,0 +1,3 @@
+#! /bin/bash
+
+echo "10ee 6028" > /sys/bus/pci/drivers/pciDriver/new_id
diff --git a/apps/xilinx2.c b/apps/xilinx2.c
new file mode 100644
index 0000000..6dd1be3
--- /dev/null
+++ b/apps/xilinx2.c
@@ -0,0 +1,179 @@
+#define _BSD_SOURCE
+#define _POSIX_C_SOURCE 199309L
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/time.h>
+
+#include "pcilib.h"
+#include "irq.h"
+#include "kmem.h"
+
+#define DEVICE "/dev/fpga0"
+#define BAR PCILIB_BAR0
+#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1)
+#define BUFFERS 1
+#define ITERATIONS 16384
+#define HUGE_PAGE 128 // number of pages per huge page
+#define PAGE_SIZE 4096 // other values are not supported in the kernel
+#define TIMEOUT 100000
+
+/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help,
+otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite
+much extra time */
+//#define USE_IRQ
+//#define CHECK_READY
+//#define REALTIME
+//#define ADD_DELAYS
+
+//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); }
+//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; }
+#define WR(addr, value) { *(uint32_t*)(bar + addr) = value; }
+#define RD(addr, value) { value = *(uint32_t*)(bar + addr); }
+
+static void fail(const char *msg, ...) {
+ va_list va;
+
+ va_start(va, msg);
+ vprintf(msg, va);
+ va_end(va);
+ printf("\n");
+
+ exit(-1);
+}
+
+void hpsleep(size_t ns) {
+ struct timespec wait, tv;
+
+ clock_gettime(CLOCK_REALTIME, &wait);
+
+ wait.tv_nsec += ns;
+ if (wait.tv_nsec > 999999999) {
+ wait.tv_sec += 1;
+ wait.tv_nsec = 1000000000 - wait.tv_nsec;
+ }
+
+ do {
+ clock_gettime(CLOCK_REALTIME, &tv);
+ } while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec)));
+}
+
+
+int main() {
+ int err;
+ int i, j;
+ pcilib_t *pci;
+ pcilib_kmem_handle_t *kbuf;
+ uint32_t status;
+ struct timeval start, end;
+ size_t size, run_time;
+ void* volatile bar;
+ uintptr_t bus_addr[BUFFERS];
+
+ pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE;
+
+#ifdef ADD_DELAYS
+ long rpt = 0, rpt2 = 0;
+ size_t best_time;
+ best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024);
+#endif /* ADD_DELAYS */
+
+#ifdef REALTIME
+ pid_t pid;
+ struct sched_param sched = {0};
+
+ pid = getpid();
+ sched.sched_priority = sched_get_priority_min(SCHED_FIFO);
+ if (sched_setscheduler(pid, SCHED_FIFO, &sched))
+ printf("Warning: not able to get real-time priority\n");
+#endif /* REALTIME */
+
+ pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT);
+ if (!pci) fail("pcilib_open");
+
+ bar = pcilib_map_bar(pci, BAR);
+ if (!bar) {
+ pcilib_close(pci);
+ fail("map bar");
+ }
+
+ // Reset
+ WR(0x00, 1)
+ usleep(1000);
+ WR(0x00, 0)
+
+ pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0);
+ pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT);
+
+ pcilib_clean_kernel_memory(pci, USE, clean_flags);
+
+ kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, 0);
+
+ WR(0x04, 0)
+ WR(0x0C, 0x20)
+ WR(0x10, (HUGE_PAGE * (PAGE_SIZE / 0x80)))
+ WR(0x14, 0x13131313)
+
+ for (j = 0; j < BUFFERS; j++ ) {
+ bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j);
+ }
+
+ gettimeofday(&start, NULL);
+
+ for (i = 0; i < ITERATIONS; i++) {
+ for (j = 0; j < BUFFERS; j++ ) {
+// uintptr_t ba = pcilib_kmem_get_block_ba(pci, kbuf, j);
+// WR(0x08, ba)
+ WR(0x08, bus_addr[j]);
+ WR(0x04, 0x01)
+
+#ifdef USE_IRQ
+ err = pcilib_wait_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT, TIMEOUT, NULL);
+ if (err) printf("Timeout waiting for IRQ, err: %i\n", err);
+
+ RD(0x04, status);
+ if ((status&0xFFFF) != 0x101) printf("Invalid status %x\n", status);
+// WR(0x04, 0x00);
+#else /* USE_IRQ */
+# ifdef ADD_DELAYS
+// hpsleep(best_time);
+ do {
+ rpt++;
+ RD(0x04, status);
+ } while (status != 0x101);
+# else /* ADD_DELAYS */
+ do {
+ RD(0x04, status);
+ } while (status != 0x101);
+# endif /* ADD_DELAYS */
+#endif /* USE_IRQ */
+
+ WR(0x00, 1)
+#ifdef CHECK_READY
+ do {
+ rpt2++;
+ RD(0x04, status);
+ } while (status != 0);
+#endif /* CHECK_READY */
+ WR(0x00, 0)
+ }
+ }
+ gettimeofday(&end, NULL);
+
+ pcilib_free_kernel_memory(pci, kbuf, 0);
+ pcilib_disable_irq(pci, 0);
+ pcilib_unmap_bar(pci, BAR, bar);
+ pcilib_close(pci);
+
+ run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
+ size = (long long int)ITERATIONS * BUFFERS * HUGE_PAGE * PAGE_SIZE;
+
+ printf("%.3lf GB/s: transfered %zu bytes in %zu us using %u buffers\n", 1000000. * size / run_time / 1024 / 1024 / 1024, size, run_time, BUFFERS);
+
+# ifdef ADD_DELAYS
+ printf("Repeats: %lf, %lf\n",1. * rpt / (ITERATIONS * BUFFERS), 1. * rpt2 / (ITERATIONS * BUFFERS));
+#endif /* USE_IRQ */
+}
diff --git a/driver/kmem.c b/driver/kmem.c
index 37a7368..ee64a78 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -130,23 +130,28 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );
break;
case PCILIB_KMEM_TYPE_PAGE:
- retptr = (void*)__get_free_pages(GFP_KERNEL, get_order(PAGE_SIZE));
+ if (kmem_handle->size == 0)
+ kmem_handle->size = PAGE_SIZE;
+ else if (kmem_handle->size%PAGE_SIZE)
+ goto kmem_alloc_mem_fail;
+
+ retptr = (void*)__get_free_pages(GFP_KERNEL|__GFP_DMA, get_order(kmem_handle->size));
kmem_entry->dma_handle = 0;
- kmem_handle->size = PAGE_SIZE;
+ kmem_handle->size = kmem_handle->size;
if (retptr) {
if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {
kmem_entry->direction = PCI_DMA_TODEVICE;
- kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE, PCI_DMA_TODEVICE);
+ kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) {
- free_page((unsigned long)retptr);
+ free_pages((unsigned long)retptr, get_order(kmem_handle->size));
goto kmem_alloc_mem_fail;
}
} else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) {
kmem_entry->direction = PCI_DMA_FROMDEVICE;
- kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) {
- free_page((unsigned long)retptr);
+ free_pages((unsigned long)retptr, get_order(kmem_handle->size));
goto kmem_alloc_mem_fail;
}
@@ -435,7 +440,7 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent
pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE);
}
}
- free_page((unsigned long)kmem_entry->cpua);
+ free_pages((unsigned long)kmem_entry->cpua, get_order(kmem_entry->size));
break;
}
diff --git a/ipecamera/ipecamera.c b/ipecamera/ipecamera.c
index 27bea77..b4bbeb8 100644
--- a/ipecamera/ipecamera.c
+++ b/ipecamera/ipecamera.c
@@ -123,7 +123,8 @@ pcilib_context_t *ipecamera_init(pcilib_t *pcilib) {
ctx->firmware = value;
break;
default:
- pcilib_error("Unsupported version of firmware (%lu)", value);
+// pcilib_error("Unsupported version of firmware (%lu)", value);
+ ;
}
#ifdef IPECAMERA_BUG_POSTPONED_READ
diff --git a/ipecamera/model.h b/ipecamera/model.h
index 4c527df..37f9096 100644
--- a/ipecamera/model.h
+++ b/ipecamera/model.h
@@ -8,7 +8,7 @@
//#define IPECAMERA_DEBUG
-#define IPECAMERA_DMA_R3
+//#define IPECAMERA_DMA_R3
#define IPECAMERA_DMA_ADDRESS 1
#define IPECAMERA_DMA_PACKET_LENGTH 4096