diff options
author | Richard Kuo <rkuo@codeaurora.org> | 2013-04-08 19:30:12 -0400 |
---|---|---|
committer | Richard Kuo <rkuo@codeaurora.org> | 2013-04-30 20:40:28 -0400 |
commit | 5e1150542fd1d75fe2b6c3491415c860cdc06be2 (patch) | |
tree | 04b129c2eb46c1d370c7647eb307465bffec45dd /arch/hexagon/kernel | |
parent | c710f5908768e18d8e8081e917fda362089cb13f (diff) |
Hexagon: use correct translations for DMA mappings
With physical offsets, pa<->va translations aren't just based
on PAGE_OFFSET anymore.
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
Diffstat (limited to 'arch/hexagon/kernel')
-rw-r--r-- | arch/hexagon/kernel/dma.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c index 65c7bdcf565e..b74f9bae31a3 100644 --- a/arch/hexagon/kernel/dma.c +++ b/arch/hexagon/kernel/dma.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * DMA implementation for Hexagon | 2 | * DMA implementation for Hexagon |
3 | * | 3 | * |
4 | * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | 4 | * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 and | 7 | * it under the terms of the GNU General Public License version 2 and |
@@ -23,12 +23,18 @@ | |||
23 | #include <linux/genalloc.h> | 23 | #include <linux/genalloc.h> |
24 | #include <asm/dma-mapping.h> | 24 | #include <asm/dma-mapping.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <asm/page.h> | ||
26 | 27 | ||
27 | struct dma_map_ops *dma_ops; | 28 | struct dma_map_ops *dma_ops; |
28 | EXPORT_SYMBOL(dma_ops); | 29 | EXPORT_SYMBOL(dma_ops); |
29 | 30 | ||
30 | int bad_dma_address; /* globals are automatically initialized to zero */ | 31 | int bad_dma_address; /* globals are automatically initialized to zero */ |
31 | 32 | ||
33 | static inline void *dma_addr_to_virt(dma_addr_t dma_addr) | ||
34 | { | ||
35 | return phys_to_virt((unsigned long) dma_addr); | ||
36 | } | ||
37 | |||
32 | int dma_supported(struct device *dev, u64 mask) | 38 | int dma_supported(struct device *dev, u64 mask) |
33 | { | 39 | { |
34 | if (mask == DMA_BIT_MASK(32)) | 40 | if (mask == DMA_BIT_MASK(32)) |
@@ -60,6 +66,12 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size, | |||
60 | { | 66 | { |
61 | void *ret; | 67 | void *ret; |
62 | 68 | ||
69 | /* | ||
70 | * Our max_low_pfn should have been backed off by 16MB in | ||
71 | * mm/init.c to create DMA coherent space. Use that as the VA | ||
72 | * for the pool. | ||
73 | */ | ||
74 | |||
63 | if (coherent_pool == NULL) { | 75 | if (coherent_pool == NULL) { |
64 | coherent_pool = gen_pool_create(PAGE_SHIFT, -1); | 76 | coherent_pool = gen_pool_create(PAGE_SHIFT, -1); |
65 | 77 | ||
@@ -67,7 +79,7 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size, | |||
67 | panic("Can't create %s() memory pool!", __func__); | 79 | panic("Can't create %s() memory pool!", __func__); |
68 | else | 80 | else |
69 | gen_pool_add(coherent_pool, | 81 | gen_pool_add(coherent_pool, |
70 | (PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)), | 82 | pfn_to_virt(max_low_pfn), |
71 | hexagon_coherent_pool_size, -1); | 83 | hexagon_coherent_pool_size, -1); |
72 | } | 84 | } |
73 | 85 | ||
@@ -75,7 +87,7 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size, | |||
75 | 87 | ||
76 | if (ret) { | 88 | if (ret) { |
77 | memset(ret, 0, size); | 89 | memset(ret, 0, size); |
78 | *dma_addr = (dma_addr_t) (ret - PAGE_OFFSET); | 90 | *dma_addr = (dma_addr_t) virt_to_phys(ret); |
79 | } else | 91 | } else |
80 | *dma_addr = ~0; | 92 | *dma_addr = ~0; |
81 | 93 | ||
@@ -118,8 +130,8 @@ static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
118 | 130 | ||
119 | s->dma_length = s->length; | 131 | s->dma_length = s->length; |
120 | 132 | ||
121 | flush_dcache_range(PAGE_OFFSET + s->dma_address, | 133 | flush_dcache_range(dma_addr_to_virt(s->dma_address), |
122 | PAGE_OFFSET + s->dma_address + s->length); | 134 | dma_addr_to_virt(s->dma_address + s->length)); |
123 | } | 135 | } |
124 | 136 | ||
125 | return nents; | 137 | return nents; |
@@ -149,11 +161,6 @@ static inline void dma_sync(void *addr, size_t size, | |||
149 | } | 161 | } |
150 | } | 162 | } |
151 | 163 | ||
152 | static inline void *dma_addr_to_virt(dma_addr_t dma_addr) | ||
153 | { | ||
154 | return phys_to_virt((unsigned long) dma_addr); | ||
155 | } | ||
156 | |||
157 | /** | 164 | /** |
158 | * hexagon_map_page() - maps an address for device DMA | 165 | * hexagon_map_page() - maps an address for device DMA |
159 | * @dev: pointer to DMA device | 166 | * @dev: pointer to DMA device |