diff options
Diffstat (limited to 'arch/x86/kernel/pci-dma.c')
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 48ab52d052b6..967dfcfa2ad2 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -186,6 +186,87 @@ static __init int iommu_setup(char *p) | |||
186 | } | 186 | } |
187 | early_param("iommu", iommu_setup); | 187 | early_param("iommu", iommu_setup); |
188 | 188 | ||
189 | #ifdef CONFIG_X86_32 | ||
190 | int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, | ||
191 | dma_addr_t device_addr, size_t size, int flags) | ||
192 | { | ||
193 | void __iomem *mem_base = NULL; | ||
194 | int pages = size >> PAGE_SHIFT; | ||
195 | int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); | ||
196 | |||
197 | if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) | ||
198 | goto out; | ||
199 | if (!size) | ||
200 | goto out; | ||
201 | if (dev->dma_mem) | ||
202 | goto out; | ||
203 | |||
204 | /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ | ||
205 | |||
206 | mem_base = ioremap(bus_addr, size); | ||
207 | if (!mem_base) | ||
208 | goto out; | ||
209 | |||
210 | dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); | ||
211 | if (!dev->dma_mem) | ||
212 | goto out; | ||
213 | dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); | ||
214 | if (!dev->dma_mem->bitmap) | ||
215 | goto free1_out; | ||
216 | |||
217 | dev->dma_mem->virt_base = mem_base; | ||
218 | dev->dma_mem->device_base = device_addr; | ||
219 | dev->dma_mem->size = pages; | ||
220 | dev->dma_mem->flags = flags; | ||
221 | |||
222 | if (flags & DMA_MEMORY_MAP) | ||
223 | return DMA_MEMORY_MAP; | ||
224 | |||
225 | return DMA_MEMORY_IO; | ||
226 | |||
227 | free1_out: | ||
228 | kfree(dev->dma_mem); | ||
229 | out: | ||
230 | if (mem_base) | ||
231 | iounmap(mem_base); | ||
232 | return 0; | ||
233 | } | ||
234 | EXPORT_SYMBOL(dma_declare_coherent_memory); | ||
235 | |||
236 | void dma_release_declared_memory(struct device *dev) | ||
237 | { | ||
238 | struct dma_coherent_mem *mem = dev->dma_mem; | ||
239 | |||
240 | if (!mem) | ||
241 | return; | ||
242 | dev->dma_mem = NULL; | ||
243 | iounmap(mem->virt_base); | ||
244 | kfree(mem->bitmap); | ||
245 | kfree(mem); | ||
246 | } | ||
247 | EXPORT_SYMBOL(dma_release_declared_memory); | ||
248 | |||
249 | void *dma_mark_declared_memory_occupied(struct device *dev, | ||
250 | dma_addr_t device_addr, size_t size) | ||
251 | { | ||
252 | struct dma_coherent_mem *mem = dev->dma_mem; | ||
253 | int pos, err; | ||
254 | int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1); | ||
255 | |||
256 | pages >>= PAGE_SHIFT; | ||
257 | |||
258 | if (!mem) | ||
259 | return ERR_PTR(-EINVAL); | ||
260 | |||
261 | pos = (device_addr - mem->device_base) >> PAGE_SHIFT; | ||
262 | err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); | ||
263 | if (err != 0) | ||
264 | return ERR_PTR(err); | ||
265 | return mem->virt_base + (pos << PAGE_SHIFT); | ||
266 | } | ||
267 | EXPORT_SYMBOL(dma_mark_declared_memory_occupied); | ||
268 | #endif /* CONFIG_X86_32 */ | ||
269 | |||
189 | int dma_supported(struct device *dev, u64 mask) | 270 | int dma_supported(struct device *dev, u64 mask) |
190 | { | 271 | { |
191 | #ifdef CONFIG_PCI | 272 | #ifdef CONFIG_PCI |