summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2014-04-03 00:37:21 +0200
committerSuren A. Chilingaryan <csa@suren.me>2014-04-03 00:37:21 +0200
commita1925232b26bc0d9801d7c1dcd58301841877af1 (patch)
tree8da70a5e091d5400fd063c385ec473d17b708583 /driver
parentd8c13eb6ff5a1c9cc28617d83dbde454c7222be4 (diff)
parentc57db04f528e671040256d322bb8f21a8d8e9ac1 (diff)
downloadpcitool-a1925232b26bc0d9801d7c1dcd58301841877af1.tar.gz
pcitool-a1925232b26bc0d9801d7c1dcd58301841877af1.tar.bz2
pcitool-a1925232b26bc0d9801d7c1dcd58301841877af1.tar.xz
pcitool-a1925232b26bc0d9801d7c1dcd58301841877af1.zip
Merge changes from xilinx_dma branch providing support of multipage kmem allocations and mapping memory regions reserved with memmap boot option
Diffstat (limited to 'driver')
-rw-r--r--driver/kmem.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/driver/kmem.c b/driver/kmem.c
index f6e22a1..4f36e79 100644
--- a/driver/kmem.c
+++ b/driver/kmem.c
@@ -135,29 +135,42 @@ 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:
flags = GFP_KERNEL;
-
+
if ((kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE)||(kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE))
flags |= __GFP_DMA;
- retptr = (void*)__get_free_pages(flags, 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(flags, get_order(kmem_handle->size));
kmem_entry->dma_handle = 0;
- kmem_handle->size = PAGE_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;
}
@@ -438,6 +451,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) {
@@ -446,7 +462,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;
}
@@ -615,12 +631,21 @@ 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) {
+ 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);