aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:25:14 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:38:57 -0500
commit92b20c40dcca2d441f367da57e7665cce15c492a (patch)
tree937e98acbbc3db12c8ed99c4499794d39287f98f /arch/powerpc/kernel
parent3bc0f40c287a435805b0545ffc44ea41f11cd43e (diff)
[POWERPC] Add an optional offset to direct DMA on 64 bits
This patch adds an optional global offset that can be added to DMA addresses when using the direct DMA operations. That brings it a step closer to the 32 bits direct DMA operations, and makes it useable on Cell when the MMU is disabled and we are using a spider southbridge. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/dma_64.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 4e6551199782..1d1dc76606ac 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -111,7 +111,11 @@ EXPORT_SYMBOL(dma_iommu_ops);
111 111
112/* 112/*
113 * Generic direct DMA implementation 113 * Generic direct DMA implementation
114 *
115 * This implementation supports a global offset that can be applied if
116 * the address at which memory is visible to devices is not 0.
114 */ 117 */
118unsigned long dma_direct_offset;
115 119
116static void *dma_direct_alloc_coherent(struct device *dev, size_t size, 120static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
117 dma_addr_t *dma_handle, gfp_t flag) 121 dma_addr_t *dma_handle, gfp_t flag)
@@ -122,7 +126,7 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
122 ret = (void *)__get_free_pages(flag, get_order(size)); 126 ret = (void *)__get_free_pages(flag, get_order(size));
123 if (ret != NULL) { 127 if (ret != NULL) {
124 memset(ret, 0, size); 128 memset(ret, 0, size);
125 *dma_handle = virt_to_abs(ret); 129 *dma_handle = virt_to_abs(ret) | dma_direct_offset;
126 } 130 }
127 return ret; 131 return ret;
128} 132}
@@ -137,7 +141,7 @@ static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
137 size_t size, 141 size_t size,
138 enum dma_data_direction direction) 142 enum dma_data_direction direction)
139{ 143{
140 return virt_to_abs(ptr); 144 return virt_to_abs(ptr) | dma_direct_offset;
141} 145}
142 146
143static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, 147static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
@@ -152,7 +156,8 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
152 int i; 156 int i;
153 157
154 for (i = 0; i < nents; i++, sg++) { 158 for (i = 0; i < nents; i++, sg++) {
155 sg->dma_address = page_to_phys(sg->page) + sg->offset; 159 sg->dma_address = (page_to_phys(sg->page) + sg->offset) |
160 dma_direct_offset;
156 sg->dma_length = sg->length; 161 sg->dma_length = sg->length;
157 } 162 }
158 163