aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/pci-nommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-08-19 10:32:42 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-22 02:34:48 -0400
commitc5e835f9641e9fcb95d1afb24906821e98b2c6a8 (patch)
tree75a79300bc4592060331bd1a928662055b976427 /arch/x86/kernel/pci-nommu.c
parente4ad68b651f22fa71820c0b30bb2807999b2b49f (diff)
x86: add alloc_coherent dma_ops callback to NOMMU driver
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/pci-nommu.c')
-rw-r--r--arch/x86/kernel/pci-nommu.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 3f91f71cdc3e..b8ce83c98211 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -72,7 +72,62 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
72 return nents; 72 return nents;
73} 73}
74 74
75static void *
76nommu_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 if (hwdev->dma_mask == NULL)
84 return NULL;
85
86 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
87 gfp |= __GFP_ZERO;
88
89 dma_mask = hwdev->coherent_dma_mask;
90 if (!dma_mask)
91 dma_mask = *(hwdev->dma_mask);
92
93 if (dma_mask < DMA_24BIT_MASK)
94 return NULL;
95
96 node = dev_to_node(hwdev);
97
98#ifdef CONFIG_X86_64
99 if (dma_mask <= DMA_32BIT_MASK)
100 gfp |= GFP_DMA32;
101#endif
102
103 /* No alloc-free penalty for ISA devices */
104 if (dma_mask == DMA_24BIT_MASK)
105 gfp |= GFP_DMA;
106
107again:
108 page = alloc_pages_node(node, gfp, get_order(size));
109 if (!page)
110 return NULL;
111
112 if ((page_to_phys(page) + size > dma_mask) && !(gfp & GFP_DMA)) {
113 free_pages((unsigned long)page_address(page), get_order(size));
114 gfp |= GFP_DMA;
115 goto again;
116 }
117
118 *dma_addr = page_to_phys(page);
119 if (check_addr("alloc_coherent", hwdev, *dma_addr, size)) {
120 flush_write_buffers();
121 return page_address(page);
122 }
123
124 free_pages((unsigned long)page_address(page), get_order(size));
125
126 return NULL;
127}
128
75struct dma_mapping_ops nommu_dma_ops = { 129struct dma_mapping_ops nommu_dma_ops = {
130 .alloc_coherent = nommu_alloc_coherent,
76 .map_single = nommu_map_single, 131 .map_single = nommu_map_single,
77 .map_sg = nommu_map_sg, 132 .map_sg = nommu_map_sg,
78 .is_phys = 1, 133 .is_phys = 1,