summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2013-07-14 05:49:19 +0200
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2013-07-14 05:49:19 +0200
commitf000eb0d43193ef8225f947226d9cd3deb00115b (patch)
tree96fba301e5e63012f7655f4277b191036f5964b3
parent7ec4581ad37b88bbb300ac00850603433a8cdfe9 (diff)
downloadipecamera-f000eb0d43193ef8225f947226d9cd3deb00115b.tar.gz
ipecamera-f000eb0d43193ef8225f947226d9cd3deb00115b.tar.bz2
ipecamera-f000eb0d43193ef8225f947226d9cd3deb00115b.tar.xz
ipecamera-f000eb0d43193ef8225f947226d9cd3deb00115b.zip
Support pre-allocated memory with memmap in KMem
-rw-r--r--apps/xilinx2.c46
-rw-r--r--driver/kmem.c30
-rw-r--r--kmem.c10
-rw-r--r--pcilib_types.h5
4 files changed, 82 insertions, 9 deletions
diff --git a/apps/xilinx2.c b/apps/xilinx2.c
index 6dd1be3..90a2b6a 100644
--- a/apps/xilinx2.c
+++ b/apps/xilinx2.c
@@ -2,6 +2,7 @@
#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
@@ -15,9 +16,10 @@
#define DEVICE "/dev/fpga0"
#define BAR PCILIB_BAR0
#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1)
+#define STATIC_REGION 0x80000000 // to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters
#define BUFFERS 1
-#define ITERATIONS 16384
-#define HUGE_PAGE 128 // number of pages per huge page
+#define ITERATIONS 100
+#define HUGE_PAGE 4096 // number of pages per huge page
#define PAGE_SIZE 4096 // other values are not supported in the kernel
#define TIMEOUT 100000
@@ -28,6 +30,7 @@ much extra time */
//#define CHECK_READY
//#define REALTIME
//#define ADD_DELAYS
+#define CHECK_RESULT
//#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; }
@@ -64,7 +67,7 @@ void hpsleep(size_t ns) {
int main() {
int err;
- int i, j;
+ long i, j;
pcilib_t *pci;
pcilib_kmem_handle_t *kbuf;
uint32_t status;
@@ -110,7 +113,30 @@ int main() {
pcilib_clean_kernel_memory(pci, USE, clean_flags);
+#ifdef STATIC_REGION
+ kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, 0);
+#else /* STATIC_REGION */
kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, 0);
+#endif /* STATIC_REGION */
+
+ if (!kbuf) {
+ printf("KMem allocation failed\n");
+ exit(0);
+ }
+
+
+#ifdef CHECK_RESULT
+ volatile uint32_t *ptr0 = pcilib_kmem_get_block_ua(pci, kbuf, 0);
+
+ memset((void*)ptr0, 0, (HUGE_PAGE * PAGE_SIZE));
+
+ for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
+ if (ptr0[i] != 0) break;
+ }
+ if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
+ printf("Initialization error in position %lu, value = %x\n", i * 4, ptr0[i]);
+ }
+#endif /* CHECK_RESULT */
WR(0x04, 0)
WR(0x0C, 0x20)
@@ -163,6 +189,18 @@ int main() {
}
gettimeofday(&end, NULL);
+
+#ifdef CHECK_RESULT
+ pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, 0);
+
+ for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
+ if (ptr0[i] != 0x13131313) break;
+ }
+ if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
+ printf("Error in position %lu, value = %x\n", i * 4, ptr0[i]);
+ }
+#endif /* CHECK_RESULT */
+
pcilib_free_kernel_memory(pci, kbuf, 0);
pcilib_disable_irq(pci, 0);
pcilib_unmap_bar(pci, BAR, bar);
@@ -176,4 +214,6 @@ int main() {
# 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 ee64a78..f36ff8c 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -129,15 +129,23 @@ int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han
case PCILIB_KMEM_TYPE_CONSISTENT:
retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );
break;
+ case PCILIB_KMEM_TYPE_REGION:
+ retptr = ioremap(kmem_handle->pa, kmem_handle->size);
+ kmem_entry->dma_handle = kmem_handle->pa;
+ if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_S2C) {
+ kmem_entry->direction = PCI_DMA_TODEVICE;
+ } else if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_C2S) {
+ kmem_entry->direction = PCI_DMA_FROMDEVICE;
+ }
+ break;
case PCILIB_KMEM_TYPE_PAGE:
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 = kmem_handle->size;
if (retptr) {
if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {
@@ -432,6 +440,9 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent
case PCILIB_KMEM_TYPE_CONSISTENT:
pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle );
break;
+ case PCILIB_KMEM_TYPE_REGION:
+ iounmap((void *)(kmem_entry->cpua));
+ break;
case PCILIB_KMEM_TYPE_PAGE:
if (kmem_entry->dma_handle) {
if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {
@@ -609,12 +620,25 @@ int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *v
virt_to_phys((void*)kmem_entry->cpua),
page_to_pfn(virt_to_page((void*)kmem_entry->cpua)));
- ret = remap_pfn_range_cpua_compat(
+ if ((kmem_entry->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) {
+ mod_info("Mapping address %08lx / Size %08lx\n",
+ kmem_entry->dma_handle,
+ (vma_size < kmem_entry->size)?vma_size:kmem_entry->size)
+
+ ret = remap_pfn_range_compat(
+ vma,
+ vma->vm_start,
+ kmem_entry->dma_handle,
+ (vma_size < kmem_entry->size)?vma_size:kmem_entry->size,
+ vma->vm_page_prot);
+ } else {
+ ret = remap_pfn_range_cpua_compat(
vma,
vma->vm_start,
kmem_entry->cpua,
(vma_size < kmem_entry->size)?vma_size:kmem_entry->size,
vma->vm_page_prot );
+ }
if (ret) {
mod_info("kmem remap failed: %d (%lx)\n", ret,kmem_entry->cpua);
diff --git a/kmem.c b/kmem.c
index d693b60..64f593a 100644
--- a/kmem.c
+++ b/kmem.c
@@ -91,13 +91,19 @@ pcilib_kmem_handle_t *pcilib_alloc_kernel_memory(pcilib_t *ctx, pcilib_kmem_type
kh.align = alignment;
kh.use = use;
- if ((type&PCILIB_KMEM_TYPE_MASK) != PCILIB_KMEM_TYPE_PAGE) {
+ if ((type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) {
+ kh.align = 0;
+ } else if ((type&PCILIB_KMEM_TYPE_MASK) != PCILIB_KMEM_TYPE_PAGE) {
kh.size += alignment;
}
-
+
for ( i = 0; i < nmemb; i++) {
kh.item = i;
kh.flags = flags;
+
+ if ((type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) {
+ kh.pa = alignment + i * size;
+ }
ret = ioctl(ctx->handle, PCIDRIVER_IOC_KMEM_ALLOC, &kh);
if (ret) {
diff --git a/pcilib_types.h b/pcilib_types.h
index f4f8f20..52c0879 100644
--- a/pcilib_types.h
+++ b/pcilib_types.h
@@ -15,7 +15,10 @@ typedef enum {
PCILIB_KMEM_TYPE_CONSISTENT = 0x00000,
PCILIB_KMEM_TYPE_PAGE = 0x10000,
PCILIB_KMEM_TYPE_DMA_S2C_PAGE = 0x10001,
- PCILIB_KMEM_TYPE_DMA_C2S_PAGE = 0x10002
+ PCILIB_KMEM_TYPE_DMA_C2S_PAGE = 0x10002,
+ PCILIB_KMEM_TYPE_REGION = 0x20000,
+ PCILIB_KMEM_TYPE_REGION_S2C = 0x20001,
+ PCILIB_KMEM_TYPE_REGION_C2S = 0x20002
} pcilib_kmem_type_t;
typedef enum {