diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/include/asm/dma-mapping.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/early-quirks.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/k8.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/pci-calgary_64.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/pci-dma.c | 146 | ||||
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 73 | ||||
-rw-r--r-- | arch/x86/kernel/pci-nommu.c | 43 |
8 files changed, 135 insertions, 170 deletions
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 9f0df9bd46b7..06ff1ba21465 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h | |||
@@ -8,7 +8,9 @@ | |||
8 | #include <asm/machvec.h> | 8 | #include <asm/machvec.h> |
9 | #include <linux/scatterlist.h> | 9 | #include <linux/scatterlist.h> |
10 | 10 | ||
11 | #define dma_alloc_coherent platform_dma_alloc_coherent | 11 | #define dma_alloc_coherent(dev, size, handle, gfp) \ |
12 | platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA) | ||
13 | |||
12 | /* coherent mem. is cheap */ | 14 | /* coherent mem. is cheap */ |
13 | static inline void * | 15 | static inline void * |
14 | dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | 16 | dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 69b4d060b21c..01c68c38840d 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -1038,8 +1038,6 @@ out: | |||
1038 | 1038 | ||
1039 | /* | 1039 | /* |
1040 | * The exported free_coherent function for dma_ops. | 1040 | * The exported free_coherent function for dma_ops. |
1041 | * FIXME: fix the generic x86 DMA layer so that it actually calls that | ||
1042 | * function. | ||
1043 | */ | 1041 | */ |
1044 | static void free_coherent(struct device *dev, size_t size, | 1042 | static void free_coherent(struct device *dev, size_t size, |
1045 | void *virt_addr, dma_addr_t dma_addr) | 1043 | void *virt_addr, dma_addr_t dma_addr) |
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 4353cf5e6fac..24bb5faf5efa 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c | |||
@@ -95,6 +95,20 @@ static void __init nvidia_bugs(int num, int slot, int func) | |||
95 | 95 | ||
96 | } | 96 | } |
97 | 97 | ||
98 | #ifdef CONFIG_DMAR | ||
99 | static void __init intel_g33_dmar(int num, int slot, int func) | ||
100 | { | ||
101 | struct acpi_table_header *dmar_tbl; | ||
102 | acpi_status status; | ||
103 | |||
104 | status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl); | ||
105 | if (ACPI_SUCCESS(status)) { | ||
106 | printk(KERN_INFO "BIOS BUG: DMAR advertised on Intel G31/G33 chipset -- ignoring\n"); | ||
107 | dmar_disabled = 1; | ||
108 | } | ||
109 | } | ||
110 | #endif | ||
111 | |||
98 | #define QFLAG_APPLY_ONCE 0x1 | 112 | #define QFLAG_APPLY_ONCE 0x1 |
99 | #define QFLAG_APPLIED 0x2 | 113 | #define QFLAG_APPLIED 0x2 |
100 | #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) | 114 | #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) |
@@ -114,6 +128,10 @@ static struct chipset early_qrk[] __initdata = { | |||
114 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, | 128 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, |
115 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, | 129 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, |
116 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, | 130 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, |
131 | #ifdef CONFIG_DMAR | ||
132 | { PCI_VENDOR_ID_INTEL, 0x29c0, | ||
133 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, intel_g33_dmar }, | ||
134 | #endif | ||
117 | {} | 135 | {} |
118 | }; | 136 | }; |
119 | 137 | ||
diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/k8.c index 7377ccb21335..304d8bad6559 100644 --- a/arch/x86/kernel/k8.c +++ b/arch/x86/kernel/k8.c | |||
@@ -16,8 +16,9 @@ EXPORT_SYMBOL(num_k8_northbridges); | |||
16 | static u32 *flush_words; | 16 | static u32 *flush_words; |
17 | 17 | ||
18 | struct pci_device_id k8_nb_ids[] = { | 18 | struct pci_device_id k8_nb_ids[] = { |
19 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, | 19 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, |
20 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, | 20 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, |
21 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, | ||
21 | {} | 22 | {} |
22 | }; | 23 | }; |
23 | EXPORT_SYMBOL(k8_nb_ids); | 24 | EXPORT_SYMBOL(k8_nb_ids); |
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index dcdac6c826e9..8415d92853c4 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c | |||
@@ -510,8 +510,22 @@ error: | |||
510 | return ret; | 510 | return ret; |
511 | } | 511 | } |
512 | 512 | ||
513 | static void calgary_free_coherent(struct device *dev, size_t size, | ||
514 | void *vaddr, dma_addr_t dma_handle) | ||
515 | { | ||
516 | unsigned int npages; | ||
517 | struct iommu_table *tbl = find_iommu_table(dev); | ||
518 | |||
519 | size = PAGE_ALIGN(size); | ||
520 | npages = size >> PAGE_SHIFT; | ||
521 | |||
522 | iommu_free(tbl, dma_handle, npages); | ||
523 | free_pages((unsigned long)vaddr, get_order(size)); | ||
524 | } | ||
525 | |||
513 | static struct dma_mapping_ops calgary_dma_ops = { | 526 | static struct dma_mapping_ops calgary_dma_ops = { |
514 | .alloc_coherent = calgary_alloc_coherent, | 527 | .alloc_coherent = calgary_alloc_coherent, |
528 | .free_coherent = calgary_free_coherent, | ||
515 | .map_single = calgary_map_single, | 529 | .map_single = calgary_map_single, |
516 | .unmap_single = calgary_unmap_single, | 530 | .unmap_single = calgary_unmap_single, |
517 | .map_sg = calgary_map_sg, | 531 | .map_sg = calgary_map_sg, |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 87d4d6964ec2..0a1408abcc62 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
@@ -41,11 +41,12 @@ EXPORT_SYMBOL(bad_dma_address); | |||
41 | /* Dummy device used for NULL arguments (normally ISA). Better would | 41 | /* Dummy device used for NULL arguments (normally ISA). Better would |
42 | be probably a smaller DMA mask, but this is bug-to-bug compatible | 42 | be probably a smaller DMA mask, but this is bug-to-bug compatible |
43 | to older i386. */ | 43 | to older i386. */ |
44 | struct device fallback_dev = { | 44 | struct device x86_dma_fallback_dev = { |
45 | .bus_id = "fallback device", | 45 | .bus_id = "fallback device", |
46 | .coherent_dma_mask = DMA_32BIT_MASK, | 46 | .coherent_dma_mask = DMA_32BIT_MASK, |
47 | .dma_mask = &fallback_dev.coherent_dma_mask, | 47 | .dma_mask = &x86_dma_fallback_dev.coherent_dma_mask, |
48 | }; | 48 | }; |
49 | EXPORT_SYMBOL(x86_dma_fallback_dev); | ||
49 | 50 | ||
50 | int dma_set_mask(struct device *dev, u64 mask) | 51 | int dma_set_mask(struct device *dev, u64 mask) |
51 | { | 52 | { |
@@ -241,147 +242,6 @@ int dma_supported(struct device *dev, u64 mask) | |||
241 | } | 242 | } |
242 | EXPORT_SYMBOL(dma_supported); | 243 | EXPORT_SYMBOL(dma_supported); |
243 | 244 | ||
244 | /* Allocate DMA memory on node near device */ | ||
245 | static noinline struct page * | ||
246 | dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order) | ||
247 | { | ||
248 | int node; | ||
249 | |||
250 | node = dev_to_node(dev); | ||
251 | |||
252 | return alloc_pages_node(node, gfp, order); | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Allocate memory for a coherent mapping. | ||
257 | */ | ||
258 | void * | ||
259 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | ||
260 | gfp_t gfp) | ||
261 | { | ||
262 | struct dma_mapping_ops *ops = get_dma_ops(dev); | ||
263 | void *memory = NULL; | ||
264 | struct page *page; | ||
265 | unsigned long dma_mask = 0; | ||
266 | dma_addr_t bus; | ||
267 | int noretry = 0; | ||
268 | |||
269 | /* ignore region specifiers */ | ||
270 | gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); | ||
271 | |||
272 | if (dma_alloc_from_coherent(dev, size, dma_handle, &memory)) | ||
273 | return memory; | ||
274 | |||
275 | if (!dev) { | ||
276 | dev = &fallback_dev; | ||
277 | gfp |= GFP_DMA; | ||
278 | } | ||
279 | dma_mask = dev->coherent_dma_mask; | ||
280 | if (dma_mask == 0) | ||
281 | dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK; | ||
282 | |||
283 | /* Device not DMA able */ | ||
284 | if (dev->dma_mask == NULL) | ||
285 | return NULL; | ||
286 | |||
287 | /* Don't invoke OOM killer or retry in lower 16MB DMA zone */ | ||
288 | if (gfp & __GFP_DMA) | ||
289 | noretry = 1; | ||
290 | |||
291 | #ifdef CONFIG_X86_64 | ||
292 | /* Why <=? Even when the mask is smaller than 4GB it is often | ||
293 | larger than 16MB and in this case we have a chance of | ||
294 | finding fitting memory in the next higher zone first. If | ||
295 | not retry with true GFP_DMA. -AK */ | ||
296 | if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) { | ||
297 | gfp |= GFP_DMA32; | ||
298 | if (dma_mask < DMA_32BIT_MASK) | ||
299 | noretry = 1; | ||
300 | } | ||
301 | #endif | ||
302 | |||
303 | again: | ||
304 | page = dma_alloc_pages(dev, | ||
305 | noretry ? gfp | __GFP_NORETRY : gfp, get_order(size)); | ||
306 | if (page == NULL) | ||
307 | return NULL; | ||
308 | |||
309 | { | ||
310 | int high, mmu; | ||
311 | bus = page_to_phys(page); | ||
312 | memory = page_address(page); | ||
313 | high = (bus + size) >= dma_mask; | ||
314 | mmu = high; | ||
315 | if (force_iommu && !(gfp & GFP_DMA)) | ||
316 | mmu = 1; | ||
317 | else if (high) { | ||
318 | free_pages((unsigned long)memory, | ||
319 | get_order(size)); | ||
320 | |||
321 | /* Don't use the 16MB ZONE_DMA unless absolutely | ||
322 | needed. It's better to use remapping first. */ | ||
323 | if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) { | ||
324 | gfp = (gfp & ~GFP_DMA32) | GFP_DMA; | ||
325 | goto again; | ||
326 | } | ||
327 | |||
328 | /* Let low level make its own zone decisions */ | ||
329 | gfp &= ~(GFP_DMA32|GFP_DMA); | ||
330 | |||
331 | if (ops->alloc_coherent) | ||
332 | return ops->alloc_coherent(dev, size, | ||
333 | dma_handle, gfp); | ||
334 | return NULL; | ||
335 | } | ||
336 | |||
337 | memset(memory, 0, size); | ||
338 | if (!mmu) { | ||
339 | *dma_handle = bus; | ||
340 | return memory; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | if (ops->alloc_coherent) { | ||
345 | free_pages((unsigned long)memory, get_order(size)); | ||
346 | gfp &= ~(GFP_DMA|GFP_DMA32); | ||
347 | return ops->alloc_coherent(dev, size, dma_handle, gfp); | ||
348 | } | ||
349 | |||
350 | if (ops->map_simple) { | ||
351 | *dma_handle = ops->map_simple(dev, virt_to_phys(memory), | ||
352 | size, | ||
353 | PCI_DMA_BIDIRECTIONAL); | ||
354 | if (*dma_handle != bad_dma_address) | ||
355 | return memory; | ||
356 | } | ||
357 | |||
358 | if (panic_on_overflow) | ||
359 | panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", | ||
360 | (unsigned long)size); | ||
361 | free_pages((unsigned long)memory, get_order(size)); | ||
362 | return NULL; | ||
363 | } | ||
364 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
365 | |||
366 | /* | ||
367 | * Unmap coherent memory. | ||
368 | * The caller must ensure that the device has finished accessing the mapping. | ||
369 | */ | ||
370 | void dma_free_coherent(struct device *dev, size_t size, | ||
371 | void *vaddr, dma_addr_t bus) | ||
372 | { | ||
373 | struct dma_mapping_ops *ops = get_dma_ops(dev); | ||
374 | |||
375 | int order = get_order(size); | ||
376 | WARN_ON(irqs_disabled()); /* for portability */ | ||
377 | if (dma_release_from_coherent(dev, order, vaddr)) | ||
378 | return; | ||
379 | if (ops->unmap_single) | ||
380 | ops->unmap_single(dev, bus, size, 0); | ||
381 | free_pages((unsigned long)vaddr, order); | ||
382 | } | ||
383 | EXPORT_SYMBOL(dma_free_coherent); | ||
384 | |||
385 | static int __init pci_iommu_init(void) | 245 | static int __init pci_iommu_init(void) |
386 | { | 246 | { |
387 | calgary_iommu_init(); | 247 | calgary_iommu_init(); |
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 49285f8fd4d5..0b99d4a06f74 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -82,7 +82,8 @@ AGPEXTERN __u32 *agp_gatt_table; | |||
82 | static unsigned long next_bit; /* protected by iommu_bitmap_lock */ | 82 | static unsigned long next_bit; /* protected by iommu_bitmap_lock */ |
83 | static int need_flush; /* global flush state. set for each gart wrap */ | 83 | static int need_flush; /* global flush state. set for each gart wrap */ |
84 | 84 | ||
85 | static unsigned long alloc_iommu(struct device *dev, int size) | 85 | static unsigned long alloc_iommu(struct device *dev, int size, |
86 | unsigned long align_mask) | ||
86 | { | 87 | { |
87 | unsigned long offset, flags; | 88 | unsigned long offset, flags; |
88 | unsigned long boundary_size; | 89 | unsigned long boundary_size; |
@@ -90,16 +91,17 @@ static unsigned long alloc_iommu(struct device *dev, int size) | |||
90 | 91 | ||
91 | base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), | 92 | base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev), |
92 | PAGE_SIZE) >> PAGE_SHIFT; | 93 | PAGE_SIZE) >> PAGE_SHIFT; |
93 | boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, | 94 | boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, |
94 | PAGE_SIZE) >> PAGE_SHIFT; | 95 | PAGE_SIZE) >> PAGE_SHIFT; |
95 | 96 | ||
96 | spin_lock_irqsave(&iommu_bitmap_lock, flags); | 97 | spin_lock_irqsave(&iommu_bitmap_lock, flags); |
97 | offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, | 98 | offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit, |
98 | size, base_index, boundary_size, 0); | 99 | size, base_index, boundary_size, align_mask); |
99 | if (offset == -1) { | 100 | if (offset == -1) { |
100 | need_flush = 1; | 101 | need_flush = 1; |
101 | offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, | 102 | offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0, |
102 | size, base_index, boundary_size, 0); | 103 | size, base_index, boundary_size, |
104 | align_mask); | ||
103 | } | 105 | } |
104 | if (offset != -1) { | 106 | if (offset != -1) { |
105 | next_bit = offset+size; | 107 | next_bit = offset+size; |
@@ -236,10 +238,10 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) | |||
236 | * Caller needs to check if the iommu is needed and flush. | 238 | * Caller needs to check if the iommu is needed and flush. |
237 | */ | 239 | */ |
238 | static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, | 240 | static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, |
239 | size_t size, int dir) | 241 | size_t size, int dir, unsigned long align_mask) |
240 | { | 242 | { |
241 | unsigned long npages = iommu_num_pages(phys_mem, size); | 243 | unsigned long npages = iommu_num_pages(phys_mem, size); |
242 | unsigned long iommu_page = alloc_iommu(dev, npages); | 244 | unsigned long iommu_page = alloc_iommu(dev, npages, align_mask); |
243 | int i; | 245 | int i; |
244 | 246 | ||
245 | if (iommu_page == -1) { | 247 | if (iommu_page == -1) { |
@@ -259,16 +261,6 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, | |||
259 | return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); | 261 | return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK); |
260 | } | 262 | } |
261 | 263 | ||
262 | static dma_addr_t | ||
263 | gart_map_simple(struct device *dev, phys_addr_t paddr, size_t size, int dir) | ||
264 | { | ||
265 | dma_addr_t map = dma_map_area(dev, paddr, size, dir); | ||
266 | |||
267 | flush_gart(); | ||
268 | |||
269 | return map; | ||
270 | } | ||
271 | |||
272 | /* Map a single area into the IOMMU */ | 264 | /* Map a single area into the IOMMU */ |
273 | static dma_addr_t | 265 | static dma_addr_t |
274 | gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) | 266 | gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) |
@@ -276,12 +268,13 @@ gart_map_single(struct device *dev, phys_addr_t paddr, size_t size, int dir) | |||
276 | unsigned long bus; | 268 | unsigned long bus; |
277 | 269 | ||
278 | if (!dev) | 270 | if (!dev) |
279 | dev = &fallback_dev; | 271 | dev = &x86_dma_fallback_dev; |
280 | 272 | ||
281 | if (!need_iommu(dev, paddr, size)) | 273 | if (!need_iommu(dev, paddr, size)) |
282 | return paddr; | 274 | return paddr; |
283 | 275 | ||
284 | bus = gart_map_simple(dev, paddr, size, dir); | 276 | bus = dma_map_area(dev, paddr, size, dir, 0); |
277 | flush_gart(); | ||
285 | 278 | ||
286 | return bus; | 279 | return bus; |
287 | } | 280 | } |
@@ -340,7 +333,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, | |||
340 | unsigned long addr = sg_phys(s); | 333 | unsigned long addr = sg_phys(s); |
341 | 334 | ||
342 | if (nonforced_iommu(dev, addr, s->length)) { | 335 | if (nonforced_iommu(dev, addr, s->length)) { |
343 | addr = dma_map_area(dev, addr, s->length, dir); | 336 | addr = dma_map_area(dev, addr, s->length, dir, 0); |
344 | if (addr == bad_dma_address) { | 337 | if (addr == bad_dma_address) { |
345 | if (i > 0) | 338 | if (i > 0) |
346 | gart_unmap_sg(dev, sg, i, dir); | 339 | gart_unmap_sg(dev, sg, i, dir); |
@@ -362,7 +355,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, | |||
362 | int nelems, struct scatterlist *sout, | 355 | int nelems, struct scatterlist *sout, |
363 | unsigned long pages) | 356 | unsigned long pages) |
364 | { | 357 | { |
365 | unsigned long iommu_start = alloc_iommu(dev, pages); | 358 | unsigned long iommu_start = alloc_iommu(dev, pages, 0); |
366 | unsigned long iommu_page = iommu_start; | 359 | unsigned long iommu_page = iommu_start; |
367 | struct scatterlist *s; | 360 | struct scatterlist *s; |
368 | int i; | 361 | int i; |
@@ -427,7 +420,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
427 | return 0; | 420 | return 0; |
428 | 421 | ||
429 | if (!dev) | 422 | if (!dev) |
430 | dev = &fallback_dev; | 423 | dev = &x86_dma_fallback_dev; |
431 | 424 | ||
432 | out = 0; | 425 | out = 0; |
433 | start = 0; | 426 | start = 0; |
@@ -499,6 +492,41 @@ error: | |||
499 | return 0; | 492 | return 0; |
500 | } | 493 | } |
501 | 494 | ||
495 | /* allocate and map a coherent mapping */ | ||
496 | static void * | ||
497 | gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr, | ||
498 | gfp_t flag) | ||
499 | { | ||
500 | void *vaddr; | ||
501 | unsigned long align_mask; | ||
502 | |||
503 | vaddr = (void *)__get_free_pages(flag | __GFP_ZERO, get_order(size)); | ||
504 | if (!vaddr) | ||
505 | return NULL; | ||
506 | |||
507 | align_mask = (1UL << get_order(size)) - 1; | ||
508 | |||
509 | *dma_addr = dma_map_area(dev, __pa(vaddr), size, DMA_BIDIRECTIONAL, | ||
510 | align_mask); | ||
511 | flush_gart(); | ||
512 | |||
513 | if (*dma_addr != bad_dma_address) | ||
514 | return vaddr; | ||
515 | |||
516 | free_pages((unsigned long)vaddr, get_order(size)); | ||
517 | |||
518 | return NULL; | ||
519 | } | ||
520 | |||
521 | /* free a coherent mapping */ | ||
522 | static void | ||
523 | gart_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
524 | dma_addr_t dma_addr) | ||
525 | { | ||
526 | gart_unmap_single(dev, dma_addr, size, DMA_BIDIRECTIONAL); | ||
527 | free_pages((unsigned long)vaddr, get_order(size)); | ||
528 | } | ||
529 | |||
502 | static int no_agp; | 530 | static int no_agp; |
503 | 531 | ||
504 | static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) | 532 | static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) |
@@ -691,7 +719,6 @@ extern int agp_amd64_init(void); | |||
691 | 719 | ||
692 | static struct dma_mapping_ops gart_dma_ops = { | 720 | static struct dma_mapping_ops gart_dma_ops = { |
693 | .map_single = gart_map_single, | 721 | .map_single = gart_map_single, |
694 | .map_simple = gart_map_simple, | ||
695 | .unmap_single = gart_unmap_single, | 722 | .unmap_single = gart_unmap_single, |
696 | .sync_single_for_cpu = NULL, | 723 | .sync_single_for_cpu = NULL, |
697 | .sync_single_for_device = NULL, | 724 | .sync_single_for_device = NULL, |
@@ -701,6 +728,8 @@ static struct dma_mapping_ops gart_dma_ops = { | |||
701 | .sync_sg_for_device = NULL, | 728 | .sync_sg_for_device = NULL, |
702 | .map_sg = gart_map_sg, | 729 | .map_sg = gart_map_sg, |
703 | .unmap_sg = gart_unmap_sg, | 730 | .unmap_sg = gart_unmap_sg, |
731 | .alloc_coherent = gart_alloc_coherent, | ||
732 | .free_coherent = gart_free_coherent, | ||
704 | }; | 733 | }; |
705 | 734 | ||
706 | void gart_iommu_shutdown(void) | 735 | void gart_iommu_shutdown(void) |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index 3f91f71cdc3e..8e398b56f50b 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c | |||
@@ -72,7 +72,50 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, | |||
72 | return nents; | 72 | return nents; |
73 | } | 73 | } |
74 | 74 | ||
75 | static void * | ||
76 | nommu_alloc_coherent(struct device *hwdev, size_t size, | ||
77 | dma_addr_t *dma_addr, gfp_t gfp) | ||
78 | { | ||
79 | unsigned long dma_mask; | ||
80 | int node; | ||
81 | struct page *page; | ||
82 | |||
83 | dma_mask = dma_alloc_coherent_mask(hwdev, gfp); | ||
84 | |||
85 | gfp |= __GFP_ZERO; | ||
86 | |||
87 | node = dev_to_node(hwdev); | ||
88 | again: | ||
89 | page = alloc_pages_node(node, gfp, get_order(size)); | ||
90 | if (!page) | ||
91 | return NULL; | ||
92 | |||
93 | if ((page_to_phys(page) + size > dma_mask) && !(gfp & GFP_DMA)) { | ||
94 | free_pages((unsigned long)page_address(page), get_order(size)); | ||
95 | gfp |= GFP_DMA; | ||
96 | goto again; | ||
97 | } | ||
98 | |||
99 | *dma_addr = page_to_phys(page); | ||
100 | if (check_addr("alloc_coherent", hwdev, *dma_addr, size)) { | ||
101 | flush_write_buffers(); | ||
102 | return page_address(page); | ||
103 | } | ||
104 | |||
105 | free_pages((unsigned long)page_address(page), get_order(size)); | ||
106 | |||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr, | ||
111 | dma_addr_t dma_addr) | ||
112 | { | ||
113 | free_pages((unsigned long)vaddr, get_order(size)); | ||
114 | } | ||
115 | |||
75 | struct dma_mapping_ops nommu_dma_ops = { | 116 | struct dma_mapping_ops nommu_dma_ops = { |
117 | .alloc_coherent = nommu_alloc_coherent, | ||
118 | .free_coherent = nommu_free_coherent, | ||
76 | .map_single = nommu_map_single, | 119 | .map_single = nommu_map_single, |
77 | .map_sg = nommu_map_sg, | 120 | .map_sg = nommu_map_sg, |
78 | .is_phys = 1, | 121 | .is_phys = 1, |