diff options
Diffstat (limited to 'arch/powerpc/kernel/dma_64.c')
-rw-r--r-- | arch/powerpc/kernel/dma_64.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 14206e3f0819..84239076a5b8 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c | |||
@@ -112,10 +112,16 @@ EXPORT_SYMBOL(dma_iommu_ops); | |||
112 | /* | 112 | /* |
113 | * Generic direct DMA implementation | 113 | * Generic direct DMA implementation |
114 | * | 114 | * |
115 | * This implementation supports a global offset that can be applied if | 115 | * This implementation supports a per-device offset that can be applied if |
116 | * the address at which memory is visible to devices is not 0. | 116 | * the address at which memory is visible to devices is not 0. Platform code |
117 | * can set archdata.dma_data to an unsigned long holding the offset. By | ||
118 | * default the offset is zero. | ||
117 | */ | 119 | */ |
118 | unsigned long dma_direct_offset; | 120 | |
121 | static unsigned long get_dma_direct_offset(struct device *dev) | ||
122 | { | ||
123 | return (unsigned long)dev->archdata.dma_data; | ||
124 | } | ||
119 | 125 | ||
120 | static void *dma_direct_alloc_coherent(struct device *dev, size_t size, | 126 | static void *dma_direct_alloc_coherent(struct device *dev, size_t size, |
121 | dma_addr_t *dma_handle, gfp_t flag) | 127 | dma_addr_t *dma_handle, gfp_t flag) |
@@ -124,13 +130,12 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size, | |||
124 | void *ret; | 130 | void *ret; |
125 | int node = dev->archdata.numa_node; | 131 | int node = dev->archdata.numa_node; |
126 | 132 | ||
127 | /* TODO: Maybe use the numa node here too ? */ | ||
128 | page = alloc_pages_node(node, flag, get_order(size)); | 133 | page = alloc_pages_node(node, flag, get_order(size)); |
129 | if (page == NULL) | 134 | if (page == NULL) |
130 | return NULL; | 135 | return NULL; |
131 | ret = page_address(page); | 136 | ret = page_address(page); |
132 | memset(ret, 0, size); | 137 | memset(ret, 0, size); |
133 | *dma_handle = virt_to_abs(ret) | dma_direct_offset; | 138 | *dma_handle = virt_to_abs(ret) + get_dma_direct_offset(dev); |
134 | 139 | ||
135 | return ret; | 140 | return ret; |
136 | } | 141 | } |
@@ -145,7 +150,7 @@ static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr, | |||
145 | size_t size, | 150 | size_t size, |
146 | enum dma_data_direction direction) | 151 | enum dma_data_direction direction) |
147 | { | 152 | { |
148 | return virt_to_abs(ptr) | dma_direct_offset; | 153 | return virt_to_abs(ptr) + get_dma_direct_offset(dev); |
149 | } | 154 | } |
150 | 155 | ||
151 | static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, | 156 | static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr, |
@@ -161,7 +166,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, | |||
161 | int i; | 166 | int i; |
162 | 167 | ||
163 | for_each_sg(sgl, sg, nents, i) { | 168 | for_each_sg(sgl, sg, nents, i) { |
164 | sg->dma_address = sg_phys(sg) | dma_direct_offset; | 169 | sg->dma_address = sg_phys(sg) + get_dma_direct_offset(dev); |
165 | sg->dma_length = sg->length; | 170 | sg->dma_length = sg->length; |
166 | } | 171 | } |
167 | 172 | ||