diff options
Diffstat (limited to 'arch/xtensa/kernel/pci-dma.c')
-rw-r--r-- | arch/xtensa/kernel/pci-dma.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index 6648fa9d9192..ca76f071666e 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/xtensa/kernel/pci-dma.c | 2 | * arch/xtensa/pci-dma.c |
3 | * | 3 | * |
4 | * DMA coherent memory allocation. | 4 | * DMA coherent memory allocation. |
5 | * | 5 | * |
@@ -29,28 +29,48 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | void * | 31 | void * |
32 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) | 32 | dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) |
33 | { | 33 | { |
34 | void *ret; | 34 | unsigned long ret; |
35 | unsigned long uncached = 0; | ||
35 | 36 | ||
36 | /* ignore region speicifiers */ | 37 | /* ignore region speicifiers */ |
37 | gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); | ||
38 | 38 | ||
39 | if (dev == NULL || (*dev->dma_mask < 0xffffffff)) | 39 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); |
40 | gfp |= GFP_DMA; | ||
41 | ret = (void *)__get_free_pages(gfp, get_order(size)); | ||
42 | 40 | ||
43 | if (ret != NULL) { | 41 | if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) |
44 | memset(ret, 0, size); | 42 | flag |= GFP_DMA; |
45 | *handle = virt_to_bus(ret); | 43 | ret = (unsigned long)__get_free_pages(flag, get_order(size)); |
44 | |||
45 | if (ret == 0) | ||
46 | return NULL; | ||
47 | |||
48 | /* We currently don't support coherent memory outside KSEG */ | ||
49 | |||
50 | if (ret < XCHAL_KSEG_CACHED_VADDR | ||
51 | || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) | ||
52 | BUG(); | ||
53 | |||
54 | |||
55 | if (ret != 0) { | ||
56 | memset((void*) ret, 0, size); | ||
57 | uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR; | ||
58 | *handle = virt_to_bus((void*)ret); | ||
59 | __flush_invalidate_dcache_range(ret, size); | ||
46 | } | 60 | } |
47 | return (void*) BYPASS_ADDR((unsigned long)ret); | 61 | |
62 | return (void*)uncached; | ||
48 | } | 63 | } |
49 | 64 | ||
50 | void dma_free_coherent(struct device *hwdev, size_t size, | 65 | void dma_free_coherent(struct device *hwdev, size_t size, |
51 | void *vaddr, dma_addr_t dma_handle) | 66 | void *vaddr, dma_addr_t dma_handle) |
52 | { | 67 | { |
53 | free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size)); | 68 | long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; |
69 | |||
70 | if (addr < 0 || addr >= XCHAL_KSEG_SIZE) | ||
71 | BUG(); | ||
72 | |||
73 | free_pages(addr, get_order(size)); | ||
54 | } | 74 | } |
55 | 75 | ||
56 | 76 | ||