aboutsummaryrefslogtreecommitdiff
path: root/arch/xtensa/kernel/pci-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel/pci-dma.c')
-rw-r--r--arch/xtensa/kernel/pci-dma.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 1ff82268e8e..2d9cc6dbfd7 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -1,5 +1,5 @@
/*
- * arch/xtensa/pci-dma.c
+ * arch/xtensa/kernel/pci-dma.c
*
* DMA coherent memory allocation.
*
@@ -20,6 +20,8 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
@@ -29,29 +31,51 @@
*/
void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
{
- void *ret;
+ unsigned long ret;
+ unsigned long uncached = 0;
/* ignore region speicifiers */
- gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
- if (dev == NULL || (*dev->dma_mask < 0xffffffff))
- gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, get_order(size));
+ flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
- if (ret != NULL) {
- memset(ret, 0, size);
- *handle = virt_to_bus(ret);
+ if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+ flag |= GFP_DMA;
+ ret = (unsigned long)__get_free_pages(flag, get_order(size));
+
+ if (ret == 0)
+ return NULL;
+
+ /* We currently don't support coherent memory outside KSEG */
+
+ if (ret < XCHAL_KSEG_CACHED_VADDR
+ || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
+ BUG();
+
+
+ if (ret != 0) {
+ memset((void*) ret, 0, size);
+ uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
+ *handle = virt_to_bus((void*)ret);
+ __flush_invalidate_dcache_range(ret, size);
}
- return (void*) BYPASS_ADDR((unsigned long)ret);
+
+ return (void*)uncached;
}
+EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+ long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+
+ if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
+ BUG();
+
+ free_pages(addr, get_order(size));
}
+EXPORT_SYMBOL(dma_free_coherent);
void consistent_sync(void *vaddr, size_t size, int direction)
@@ -71,3 +95,4 @@ void consistent_sync(void *vaddr, size_t size, int direction)
break;
}
}
+EXPORT_SYMBOL(consistent_sync);