diff options
author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2013-07-14 05:49:19 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2013-07-14 05:49:19 +0200 |
commit | f000eb0d43193ef8225f947226d9cd3deb00115b (patch) | |
tree | 96fba301e5e63012f7655f4277b191036f5964b3 | |
parent | 7ec4581ad37b88bbb300ac00850603433a8cdfe9 (diff) | |
download | ipecamera-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.c | 46 | ||||
-rw-r--r-- | driver/kmem.c | 30 | ||||
-rw-r--r-- | kmem.c | 10 | ||||
-rw-r--r-- | pcilib_types.h | 5 |
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); @@ -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 { |