aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:25:02 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:38:40 -0500
commit12d04eef927bf61328af2c7cbe756c96f98ac3bf (patch)
tree18865369100e9059c7e883dec93ea67f7b52a287 /arch/powerpc/kernel
parent7c719871ff4d5f15b71f0138d08b758281b58631 (diff)
[POWERPC] Refactor 64 bits DMA operations
This patch completely refactors DMA operations for 64 bits powerpc. 32 bits is untouched for now. We use the new dev_archdata structure to add the dma operations pointer and associated data to struct device. While at it, we also add the OF node pointer and numa node. In the future, we might want to look into merging that with pci_dn as well. The old vio, pci-iommu and pci-direct DMA ops are gone. They are now replaced by a set of generic iommu and direct DMA ops (non PCI specific) that can be used by bus types. The toplevel implementation is now inline. 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/Makefile3
-rw-r--r--arch/powerpc/kernel/dma_64.c240
-rw-r--r--arch/powerpc/kernel/ibmebus.c6
-rw-r--r--arch/powerpc/kernel/iommu.c6
-rw-r--r--arch/powerpc/kernel/of_platform.c9
-rw-r--r--arch/powerpc/kernel/pci_64.c26
-rw-r--r--arch/powerpc/kernel/pci_direct_iommu.c98
-rw-r--r--arch/powerpc/kernel/pci_iommu.c164
-rw-r--r--arch/powerpc/kernel/setup_64.c1
-rw-r--r--arch/powerpc/kernel/vio.c94
10 files changed, 199 insertions, 448 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 04fdbe568d7b..eba8d118e214 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -62,8 +62,7 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
62module-$(CONFIG_PPC64) += module_64.o 62module-$(CONFIG_PPC64) += module_64.o
63obj-$(CONFIG_MODULES) += $(module-y) 63obj-$(CONFIG_MODULES) += $(module-y)
64 64
65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ 65pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o
66 pci_direct_iommu.o iomap.o
67pci32-$(CONFIG_PPC32) := pci_32.o 66pci32-$(CONFIG_PPC32) := pci_32.o
68obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) 67obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
69kexec-$(CONFIG_PPC64) := machine_kexec_64.o 68kexec-$(CONFIG_PPC64) := machine_kexec_64.o
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 6c168f6ea142..4e6551199782 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -1,151 +1,185 @@
1/* 1/*
2 * Copyright (C) 2004 IBM Corporation 2 * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corporation
3 * 3 *
4 * Implements the generic device dma API for ppc64. Handles 4 * Provide default implementations of the DMA mapping callbacks for
5 * the pci and vio busses 5 * directly mapped busses and busses using the iommu infrastructure
6 */ 6 */
7 7
8#include <linux/device.h> 8#include <linux/device.h>
9#include <linux/dma-mapping.h> 9#include <linux/dma-mapping.h>
10/* Include the busses we support */
11#include <linux/pci.h>
12#include <asm/vio.h>
13#include <asm/ibmebus.h>
14#include <asm/scatterlist.h>
15#include <asm/bug.h> 10#include <asm/bug.h>
11#include <asm/iommu.h>
12#include <asm/abs_addr.h>
16 13
17static struct dma_mapping_ops *get_dma_ops(struct device *dev) 14/*
18{ 15 * Generic iommu implementation
19#ifdef CONFIG_PCI 16 */
20 if (dev->bus == &pci_bus_type)
21 return &pci_dma_ops;
22#endif
23#ifdef CONFIG_IBMVIO
24 if (dev->bus == &vio_bus_type)
25 return &vio_dma_ops;
26#endif
27#ifdef CONFIG_IBMEBUS
28 if (dev->bus == &ibmebus_bus_type)
29 return &ibmebus_dma_ops;
30#endif
31 return NULL;
32}
33 17
34int dma_supported(struct device *dev, u64 mask) 18static inline unsigned long device_to_mask(struct device *dev)
35{ 19{
36 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 20 if (dev->dma_mask && *dev->dma_mask)
21 return *dev->dma_mask;
22 /* Assume devices without mask can take 32 bit addresses */
23 return 0xfffffffful;
24}
37 25
38 BUG_ON(!dma_ops);
39 26
40 return dma_ops->dma_supported(dev, mask); 27/* Allocates a contiguous real buffer and creates mappings over it.
28 * Returns the virtual address of the buffer and sets dma_handle
29 * to the dma address (mapping) of the first page.
30 */
31static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
32 dma_addr_t *dma_handle, gfp_t flag)
33{
34 return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
35 device_to_mask(dev), flag,
36 dev->archdata.numa_node);
41} 37}
42EXPORT_SYMBOL(dma_supported);
43 38
44int dma_set_mask(struct device *dev, u64 dma_mask) 39static void dma_iommu_free_coherent(struct device *dev, size_t size,
40 void *vaddr, dma_addr_t dma_handle)
45{ 41{
46#ifdef CONFIG_PCI 42 iommu_free_coherent(dev->archdata.dma_data, size, vaddr, dma_handle);
47 if (dev->bus == &pci_bus_type)
48 return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
49#endif
50#ifdef CONFIG_IBMVIO
51 if (dev->bus == &vio_bus_type)
52 return -EIO;
53#endif /* CONFIG_IBMVIO */
54#ifdef CONFIG_IBMEBUS
55 if (dev->bus == &ibmebus_bus_type)
56 return -EIO;
57#endif
58 BUG();
59 return 0;
60} 43}
61EXPORT_SYMBOL(dma_set_mask);
62 44
63void *dma_alloc_coherent(struct device *dev, size_t size, 45/* Creates TCEs for a user provided buffer. The user buffer must be
64 dma_addr_t *dma_handle, gfp_t flag) 46 * contiguous real kernel storage (not vmalloc). The address of the buffer
47 * passed here is the kernel (virtual) address of the buffer. The buffer
48 * need not be page aligned, the dma_addr_t returned will point to the same
49 * byte within the page as vaddr.
50 */
51static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
52 size_t size,
53 enum dma_data_direction direction)
65{ 54{
66 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 55 return iommu_map_single(dev->archdata.dma_data, vaddr, size,
67 56 device_to_mask(dev), direction);
68 BUG_ON(!dma_ops);
69
70 return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
71} 57}
72EXPORT_SYMBOL(dma_alloc_coherent);
73 58
74void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, 59
75 dma_addr_t dma_handle) 60static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
61 size_t size,
62 enum dma_data_direction direction)
76{ 63{
77 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 64 iommu_unmap_single(dev->archdata.dma_data, dma_handle, size, direction);
65}
78 66
79 BUG_ON(!dma_ops);
80 67
81 dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); 68static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
69 int nelems, enum dma_data_direction direction)
70{
71 return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
72 device_to_mask(dev), direction);
82} 73}
83EXPORT_SYMBOL(dma_free_coherent);
84 74
85dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, 75static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
86 enum dma_data_direction direction) 76 int nelems, enum dma_data_direction direction)
87{ 77{
88 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 78 iommu_unmap_sg(dev->archdata.dma_data, sglist, nelems, direction);
89
90 BUG_ON(!dma_ops);
91
92 return dma_ops->map_single(dev, cpu_addr, size, direction);
93} 79}
94EXPORT_SYMBOL(dma_map_single);
95 80
96void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, 81/* We support DMA to/from any memory page via the iommu */
97 enum dma_data_direction direction) 82static int dma_iommu_dma_supported(struct device *dev, u64 mask)
98{ 83{
99 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 84 struct iommu_table *tbl = dev->archdata.dma_data;
100 85
101 BUG_ON(!dma_ops); 86 if (!tbl || tbl->it_offset > mask) {
102 87 printk(KERN_INFO
103 dma_ops->unmap_single(dev, dma_addr, size, direction); 88 "Warning: IOMMU offset too big for device mask\n");
89 if (tbl)
90 printk(KERN_INFO
91 "mask: 0x%08lx, table offset: 0x%08lx\n",
92 mask, tbl->it_offset);
93 else
94 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
95 mask);
96 return 0;
97 } else
98 return 1;
104} 99}
105EXPORT_SYMBOL(dma_unmap_single);
106 100
107dma_addr_t dma_map_page(struct device *dev, struct page *page, 101struct dma_mapping_ops dma_iommu_ops = {
108 unsigned long offset, size_t size, 102 .alloc_coherent = dma_iommu_alloc_coherent,
109 enum dma_data_direction direction) 103 .free_coherent = dma_iommu_free_coherent,
110{ 104 .map_single = dma_iommu_map_single,
111 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 105 .unmap_single = dma_iommu_unmap_single,
106 .map_sg = dma_iommu_map_sg,
107 .unmap_sg = dma_iommu_unmap_sg,
108 .dma_supported = dma_iommu_dma_supported,
109};
110EXPORT_SYMBOL(dma_iommu_ops);
112 111
113 BUG_ON(!dma_ops); 112/*
113 * Generic direct DMA implementation
114 */
114 115
115 return dma_ops->map_single(dev, page_address(page) + offset, size, 116static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
116 direction); 117 dma_addr_t *dma_handle, gfp_t flag)
118{
119 void *ret;
120
121 /* TODO: Maybe use the numa node here too ? */
122 ret = (void *)__get_free_pages(flag, get_order(size));
123 if (ret != NULL) {
124 memset(ret, 0, size);
125 *dma_handle = virt_to_abs(ret);
126 }
127 return ret;
117} 128}
118EXPORT_SYMBOL(dma_map_page);
119 129
120void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, 130static void dma_direct_free_coherent(struct device *dev, size_t size,
121 enum dma_data_direction direction) 131 void *vaddr, dma_addr_t dma_handle)
122{ 132{
123 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 133 free_pages((unsigned long)vaddr, get_order(size));
134}
124 135
125 BUG_ON(!dma_ops); 136static dma_addr_t dma_direct_map_single(struct device *dev, void *ptr,
137 size_t size,
138 enum dma_data_direction direction)
139{
140 return virt_to_abs(ptr);
141}
126 142
127 dma_ops->unmap_single(dev, dma_address, size, direction); 143static void dma_direct_unmap_single(struct device *dev, dma_addr_t dma_addr,
144 size_t size,
145 enum dma_data_direction direction)
146{
128} 147}
129EXPORT_SYMBOL(dma_unmap_page);
130 148
131int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, 149static int dma_direct_map_sg(struct device *dev, struct scatterlist *sg,
132 enum dma_data_direction direction) 150 int nents, enum dma_data_direction direction)
133{ 151{
134 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 152 int i;
135 153
136 BUG_ON(!dma_ops); 154 for (i = 0; i < nents; i++, sg++) {
155 sg->dma_address = page_to_phys(sg->page) + sg->offset;
156 sg->dma_length = sg->length;
157 }
137 158
138 return dma_ops->map_sg(dev, sg, nents, direction); 159 return nents;
139} 160}
140EXPORT_SYMBOL(dma_map_sg);
141 161
142void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, 162static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
143 enum dma_data_direction direction) 163 int nents, enum dma_data_direction direction)
144{ 164{
145 struct dma_mapping_ops *dma_ops = get_dma_ops(dev); 165}
146
147 BUG_ON(!dma_ops);
148 166
149 dma_ops->unmap_sg(dev, sg, nhwentries, direction); 167static int dma_direct_dma_supported(struct device *dev, u64 mask)
168{
169 /* Could be improved to check for memory though it better be
170 * done via some global so platforms can set the limit in case
171 * they have limited DMA windows
172 */
173 return mask >= DMA_32BIT_MASK;
150} 174}
151EXPORT_SYMBOL(dma_unmap_sg); 175
176struct dma_mapping_ops dma_direct_ops = {
177 .alloc_coherent = dma_direct_alloc_coherent,
178 .free_coherent = dma_direct_free_coherent,
179 .map_single = dma_direct_map_single,
180 .unmap_single = dma_direct_unmap_single,
181 .map_sg = dma_direct_map_sg,
182 .unmap_sg = dma_direct_unmap_sg,
183 .dma_supported = dma_direct_dma_supported,
184};
185EXPORT_SYMBOL(dma_direct_ops);
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 39db7a3affe1..8e515797de6a 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -112,7 +112,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask)
112 return 1; 112 return 1;
113} 113}
114 114
115struct dma_mapping_ops ibmebus_dma_ops = { 115static struct dma_mapping_ops ibmebus_dma_ops = {
116 .alloc_coherent = ibmebus_alloc_coherent, 116 .alloc_coherent = ibmebus_alloc_coherent,
117 .free_coherent = ibmebus_free_coherent, 117 .free_coherent = ibmebus_free_coherent,
118 .map_single = ibmebus_map_single, 118 .map_single = ibmebus_map_single,
@@ -176,6 +176,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common(
176 dev->ofdev.dev.bus = &ibmebus_bus_type; 176 dev->ofdev.dev.bus = &ibmebus_bus_type;
177 dev->ofdev.dev.release = ibmebus_dev_release; 177 dev->ofdev.dev.release = ibmebus_dev_release;
178 178
179 dev->ofdev.dev.archdata.of_node = dev->ofdev.node;
180 dev->ofdev.dev.archdata.dma_ops = &ibmebus_dma_ops;
181 dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node);
182
179 /* An ibmebusdev is based on a of_device. We have to change the 183 /* An ibmebusdev is based on a of_device. We have to change the
180 * bus type to use our own DMA mapping operations. 184 * bus type to use our own DMA mapping operations.
181 */ 185 */
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ba6b7256084b..95edad4faf26 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -258,9 +258,9 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
258 spin_unlock_irqrestore(&(tbl->it_lock), flags); 258 spin_unlock_irqrestore(&(tbl->it_lock), flags);
259} 259}
260 260
261int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 261int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
262 struct scatterlist *sglist, int nelems, 262 int nelems, unsigned long mask,
263 unsigned long mask, enum dma_data_direction direction) 263 enum dma_data_direction direction)
264{ 264{
265 dma_addr_t dma_next = 0, dma_addr; 265 dma_addr_t dma_next = 0, dma_addr;
266 unsigned long flags; 266 unsigned long flags;
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 25850ade8e68..7a0e77af7c9f 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -22,7 +22,7 @@
22#include <asm/dcr.h> 22#include <asm/dcr.h>
23#include <asm/of_device.h> 23#include <asm/of_device.h>
24#include <asm/of_platform.h> 24#include <asm/of_platform.h>
25 25#include <asm/topology.h>
26 26
27/* 27/*
28 * The list of OF IDs below is used for matching bus types in the 28 * The list of OF IDs below is used for matching bus types in the
@@ -221,6 +221,13 @@ struct of_device* of_platform_device_create(struct device_node *np,
221 dev->dev.parent = parent; 221 dev->dev.parent = parent;
222 dev->dev.bus = &of_platform_bus_type; 222 dev->dev.bus = &of_platform_bus_type;
223 dev->dev.release = of_release_dev; 223 dev->dev.release = of_release_dev;
224 dev->dev.archdata.of_node = np;
225 dev->dev.archdata.numa_node = of_node_to_nid(np);
226
227 /* We do not fill the DMA ops for platform devices by default.
228 * This is currently the responsibility of the platform code
229 * to do such, possibly using a device notifier
230 */
224 231
225 if (bus_id) 232 if (bus_id)
226 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); 233 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 9a6bb80a8cd4..88b78484b944 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -61,7 +61,7 @@ void iSeries_pcibios_init(void);
61 61
62LIST_HEAD(hose_list); 62LIST_HEAD(hose_list);
63 63
64struct dma_mapping_ops pci_dma_ops; 64struct dma_mapping_ops *pci_dma_ops;
65EXPORT_SYMBOL(pci_dma_ops); 65EXPORT_SYMBOL(pci_dma_ops);
66 66
67int global_phb_number; /* Global phb counter */ 67int global_phb_number; /* Global phb counter */
@@ -1205,15 +1205,35 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
1205} 1205}
1206EXPORT_SYMBOL(pcibios_fixup_device_resources); 1206EXPORT_SYMBOL(pcibios_fixup_device_resources);
1207 1207
1208void __devinit pcibios_setup_new_device(struct pci_dev *dev)
1209{
1210 struct dev_archdata *sd = &dev->dev.archdata;
1211
1212 sd->of_node = pci_device_to_OF_node(dev);
1213
1214 DBG("PCI device %s OF node: %s\n", pci_name(dev),
1215 sd->of_node ? sd->of_node->full_name : "<none>");
1216
1217 sd->dma_ops = pci_dma_ops;
1218#ifdef CONFIG_NUMA
1219 sd->numa_node = pcibus_to_node(dev->bus);
1220#else
1221 sd->numa_node = -1;
1222#endif
1223 if (ppc_md.pci_dma_dev_setup)
1224 ppc_md.pci_dma_dev_setup(dev);
1225}
1226EXPORT_SYMBOL(pcibios_setup_new_device);
1208 1227
1209static void __devinit do_bus_setup(struct pci_bus *bus) 1228static void __devinit do_bus_setup(struct pci_bus *bus)
1210{ 1229{
1211 struct pci_dev *dev; 1230 struct pci_dev *dev;
1212 1231
1213 ppc_md.iommu_bus_setup(bus); 1232 if (ppc_md.pci_dma_bus_setup)
1233 ppc_md.pci_dma_bus_setup(bus);
1214 1234
1215 list_for_each_entry(dev, &bus->devices, bus_list) 1235 list_for_each_entry(dev, &bus->devices, bus_list)
1216 ppc_md.iommu_dev_setup(dev); 1236 pcibios_setup_new_device(dev);
1217 1237
1218 /* Read default IRQs and fixup if necessary */ 1238 /* Read default IRQs and fixup if necessary */
1219 list_for_each_entry(dev, &bus->devices, bus_list) { 1239 list_for_each_entry(dev, &bus->devices, bus_list) {
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c
deleted file mode 100644
index 72ce082ce738..000000000000
--- a/arch/powerpc/kernel/pci_direct_iommu.c
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 * Support for DMA from PCI devices to main memory on
3 * machines without an iommu or with directly addressable
4 * RAM (typically a pmac with 2Gb of RAM or less)
5 *
6 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/delay.h>
17#include <linux/string.h>
18#include <linux/init.h>
19#include <linux/bootmem.h>
20#include <linux/mm.h>
21#include <linux/dma-mapping.h>
22
23#include <asm/sections.h>
24#include <asm/io.h>
25#include <asm/prom.h>
26#include <asm/pci-bridge.h>
27#include <asm/machdep.h>
28#include <asm/pmac_feature.h>
29#include <asm/abs_addr.h>
30#include <asm/ppc-pci.h>
31
32static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
33 dma_addr_t *dma_handle, gfp_t flag)
34{
35 void *ret;
36
37 ret = (void *)__get_free_pages(flag, get_order(size));
38 if (ret != NULL) {
39 memset(ret, 0, size);
40 *dma_handle = virt_to_abs(ret);
41 }
42 return ret;
43}
44
45static void pci_direct_free_coherent(struct device *hwdev, size_t size,
46 void *vaddr, dma_addr_t dma_handle)
47{
48 free_pages((unsigned long)vaddr, get_order(size));
49}
50
51static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr,
52 size_t size, enum dma_data_direction direction)
53{
54 return virt_to_abs(ptr);
55}
56
57static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
58 size_t size, enum dma_data_direction direction)
59{
60}
61
62static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg,
63 int nents, enum dma_data_direction direction)
64{
65 int i;
66
67 for (i = 0; i < nents; i++, sg++) {
68 sg->dma_address = page_to_phys(sg->page) + sg->offset;
69 sg->dma_length = sg->length;
70 }
71
72 return nents;
73}
74
75static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg,
76 int nents, enum dma_data_direction direction)
77{
78}
79
80static int pci_direct_dma_supported(struct device *dev, u64 mask)
81{
82 return mask < 0x100000000ull;
83}
84
85static struct dma_mapping_ops pci_direct_ops = {
86 .alloc_coherent = pci_direct_alloc_coherent,
87 .free_coherent = pci_direct_free_coherent,
88 .map_single = pci_direct_map_single,
89 .unmap_single = pci_direct_unmap_single,
90 .map_sg = pci_direct_map_sg,
91 .unmap_sg = pci_direct_unmap_sg,
92 .dma_supported = pci_direct_dma_supported,
93};
94
95void __init pci_direct_iommu_init(void)
96{
97 pci_dma_ops = pci_direct_ops;
98}
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
deleted file mode 100644
index 0688b2534acb..000000000000
--- a/arch/powerpc/kernel/pci_iommu.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
3 *
4 * Rewrite, cleanup, new allocation schemes:
5 * Copyright (C) 2004 Olof Johansson, IBM Corporation
6 *
7 * Dynamic DMA mapping support, platform-independent parts.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24
25#include <linux/init.h>
26#include <linux/types.h>
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/spinlock.h>
30#include <linux/string.h>
31#include <linux/pci.h>
32#include <linux/dma-mapping.h>
33#include <asm/io.h>
34#include <asm/prom.h>
35#include <asm/iommu.h>
36#include <asm/pci-bridge.h>
37#include <asm/machdep.h>
38#include <asm/ppc-pci.h>
39
40/*
41 * We can use ->sysdata directly and avoid the extra work in
42 * pci_device_to_OF_node since ->sysdata will have been initialised
43 * in the iommu init code for all devices.
44 */
45#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
46
47static inline struct iommu_table *device_to_table(struct device *hwdev)
48{
49 struct pci_dev *pdev;
50
51 if (!hwdev) {
52 pdev = ppc64_isabridge_dev;
53 if (!pdev)
54 return NULL;
55 } else
56 pdev = to_pci_dev(hwdev);
57
58 return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
59}
60
61
62static inline unsigned long device_to_mask(struct device *hwdev)
63{
64 struct pci_dev *pdev;
65
66 if (!hwdev) {
67 pdev = ppc64_isabridge_dev;
68 if (!pdev) /* This is the best guess we can do */
69 return 0xfffffffful;
70 } else
71 pdev = to_pci_dev(hwdev);
72
73 if (pdev->dma_mask)
74 return pdev->dma_mask;
75
76 /* Assume devices without mask can take 32 bit addresses */
77 return 0xfffffffful;
78}
79
80
81/* Allocates a contiguous real buffer and creates mappings over it.
82 * Returns the virtual address of the buffer and sets dma_handle
83 * to the dma address (mapping) of the first page.
84 */
85static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
86 dma_addr_t *dma_handle, gfp_t flag)
87{
88 return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
89 device_to_mask(hwdev), flag,
90 pcibus_to_node(to_pci_dev(hwdev)->bus));
91}
92
93static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
94 void *vaddr, dma_addr_t dma_handle)
95{
96 iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
97}
98
99/* Creates TCEs for a user provided buffer. The user buffer must be
100 * contiguous real kernel storage (not vmalloc). The address of the buffer
101 * passed here is the kernel (virtual) address of the buffer. The buffer
102 * need not be page aligned, the dma_addr_t returned will point to the same
103 * byte within the page as vaddr.
104 */
105static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
106 size_t size, enum dma_data_direction direction)
107{
108 return iommu_map_single(device_to_table(hwdev), vaddr, size,
109 device_to_mask(hwdev), direction);
110}
111
112
113static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
114 size_t size, enum dma_data_direction direction)
115{
116 iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
117}
118
119
120static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
121 int nelems, enum dma_data_direction direction)
122{
123 return iommu_map_sg(pdev, device_to_table(pdev), sglist,
124 nelems, device_to_mask(pdev), direction);
125}
126
127static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
128 int nelems, enum dma_data_direction direction)
129{
130 iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
131}
132
133/* We support DMA to/from any memory page via the iommu */
134static int pci_iommu_dma_supported(struct device *dev, u64 mask)
135{
136 struct iommu_table *tbl = device_to_table(dev);
137
138 if (!tbl || tbl->it_offset > mask) {
139 printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
140 if (tbl)
141 printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
142 mask, tbl->it_offset);
143 else
144 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
145 mask);
146 return 0;
147 } else
148 return 1;
149}
150
151struct dma_mapping_ops pci_iommu_ops = {
152 .alloc_coherent = pci_iommu_alloc_coherent,
153 .free_coherent = pci_iommu_free_coherent,
154 .map_single = pci_iommu_map_single,
155 .unmap_single = pci_iommu_unmap_single,
156 .map_sg = pci_iommu_map_sg,
157 .unmap_sg = pci_iommu_unmap_sg,
158 .dma_supported = pci_iommu_dma_supported,
159};
160
161void pci_iommu_init(void)
162{
163 pci_dma_ops = pci_iommu_ops;
164}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index b0f1c82df994..f7ad64acf47e 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -33,6 +33,7 @@
33#include <linux/serial.h> 33#include <linux/serial.h>
34#include <linux/serial_8250.h> 34#include <linux/serial_8250.h>
35#include <linux/bootmem.h> 35#include <linux/bootmem.h>
36#include <linux/pci.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/kdump.h> 38#include <asm/kdump.h>
38#include <asm/prom.h> 39#include <asm/prom.h>
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index ed007878d1bf..a80f8f1d2e5d 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -81,15 +81,15 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
81 struct iommu_table *tbl; 81 struct iommu_table *tbl;
82 unsigned long offset, size; 82 unsigned long offset, size;
83 83
84 dma_window = get_property(dev->dev.platform_data, 84 dma_window = get_property(dev->dev.archdata.of_node,
85 "ibm,my-dma-window", NULL); 85 "ibm,my-dma-window", NULL);
86 if (!dma_window) 86 if (!dma_window)
87 return NULL; 87 return NULL;
88 88
89 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); 89 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
90 90
91 of_parse_dma_window(dev->dev.platform_data, dma_window, 91 of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
92 &tbl->it_index, &offset, &size); 92 &tbl->it_index, &offset, &size);
93 93
94 /* TCE table size - measured in tce entries */ 94 /* TCE table size - measured in tce entries */
95 tbl->it_size = size >> IOMMU_PAGE_SHIFT; 95 tbl->it_size = size >> IOMMU_PAGE_SHIFT;
@@ -117,7 +117,8 @@ static const struct vio_device_id *vio_match_device(
117{ 117{
118 while (ids->type[0] != '\0') { 118 while (ids->type[0] != '\0') {
119 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && 119 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
120 device_is_compatible(dev->dev.platform_data, ids->compat)) 120 device_is_compatible(dev->dev.archdata.of_node,
121 ids->compat))
121 return ids; 122 return ids;
122 ids++; 123 ids++;
123 } 124 }
@@ -198,9 +199,9 @@ EXPORT_SYMBOL(vio_unregister_driver);
198/* vio_dev refcount hit 0 */ 199/* vio_dev refcount hit 0 */
199static void __devinit vio_dev_release(struct device *dev) 200static void __devinit vio_dev_release(struct device *dev)
200{ 201{
201 if (dev->platform_data) { 202 if (dev->archdata.of_node) {
202 /* XXX free TCE table */ 203 /* XXX should free TCE table */
203 of_node_put(dev->platform_data); 204 of_node_put(dev->archdata.of_node);
204 } 205 }
205 kfree(to_vio_dev(dev)); 206 kfree(to_vio_dev(dev));
206} 207}
@@ -210,7 +211,7 @@ static void __devinit vio_dev_release(struct device *dev)
210 * @of_node: The OF node for this device. 211 * @of_node: The OF node for this device.
211 * 212 *
212 * Creates and initializes a vio_dev structure from the data in 213 * Creates and initializes a vio_dev structure from the data in
213 * of_node (dev.platform_data) and adds it to the list of virtual devices. 214 * of_node and adds it to the list of virtual devices.
214 * Returns a pointer to the created vio_dev or NULL if node has 215 * Returns a pointer to the created vio_dev or NULL if node has
215 * NULL device_type or compatible fields. 216 * NULL device_type or compatible fields.
216 */ 217 */
@@ -240,8 +241,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
240 if (viodev == NULL) 241 if (viodev == NULL)
241 return NULL; 242 return NULL;
242 243
243 viodev->dev.platform_data = of_node_get(of_node);
244
245 viodev->irq = irq_of_parse_and_map(of_node, 0); 244 viodev->irq = irq_of_parse_and_map(of_node, 0);
246 245
247 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); 246 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
@@ -254,7 +253,10 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
254 if (unit_address != NULL) 253 if (unit_address != NULL)
255 viodev->unit_address = *unit_address; 254 viodev->unit_address = *unit_address;
256 } 255 }
257 viodev->iommu_table = vio_build_iommu_table(viodev); 256 viodev->dev.archdata.of_node = of_node_get(of_node);
257 viodev->dev.archdata.dma_ops = &dma_iommu_ops;
258 viodev->dev.archdata.dma_data = vio_build_iommu_table(viodev);
259 viodev->dev.archdata.numa_node = of_node_to_nid(of_node);
258 260
259 /* init generic 'struct device' fields: */ 261 /* init generic 'struct device' fields: */
260 viodev->dev.parent = &vio_bus_device.dev; 262 viodev->dev.parent = &vio_bus_device.dev;
@@ -285,10 +287,11 @@ static int __init vio_bus_init(void)
285#ifdef CONFIG_PPC_ISERIES 287#ifdef CONFIG_PPC_ISERIES
286 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 288 if (firmware_has_feature(FW_FEATURE_ISERIES)) {
287 iommu_vio_init(); 289 iommu_vio_init();
288 vio_bus_device.iommu_table = &vio_iommu_table; 290 vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
291 vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
289 iSeries_vio_dev = &vio_bus_device.dev; 292 iSeries_vio_dev = &vio_bus_device.dev;
290 } 293 }
291#endif 294#endif /* CONFIG_PPC_ISERIES */
292 295
293 err = bus_register(&vio_bus_type); 296 err = bus_register(&vio_bus_type);
294 if (err) { 297 if (err) {
@@ -336,7 +339,7 @@ static ssize_t name_show(struct device *dev,
336static ssize_t devspec_show(struct device *dev, 339static ssize_t devspec_show(struct device *dev,
337 struct device_attribute *attr, char *buf) 340 struct device_attribute *attr, char *buf)
338{ 341{
339 struct device_node *of_node = dev->platform_data; 342 struct device_node *of_node = dev->archdata.of_node;
340 343
341 return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); 344 return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
342} 345}
@@ -353,62 +356,6 @@ void __devinit vio_unregister_device(struct vio_dev *viodev)
353} 356}
354EXPORT_SYMBOL(vio_unregister_device); 357EXPORT_SYMBOL(vio_unregister_device);
355 358
356static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
357 size_t size, enum dma_data_direction direction)
358{
359 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
360 ~0ul, direction);
361}
362
363static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
364 size_t size, enum dma_data_direction direction)
365{
366 iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
367 direction);
368}
369
370static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
371 int nelems, enum dma_data_direction direction)
372{
373 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
374 nelems, ~0ul, direction);
375}
376
377static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
378 int nelems, enum dma_data_direction direction)
379{
380 iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
381}
382
383static void *vio_alloc_coherent(struct device *dev, size_t size,
384 dma_addr_t *dma_handle, gfp_t flag)
385{
386 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
387 dma_handle, ~0ul, flag, -1);
388}
389
390static void vio_free_coherent(struct device *dev, size_t size,
391 void *vaddr, dma_addr_t dma_handle)
392{
393 iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
394 dma_handle);
395}
396
397static int vio_dma_supported(struct device *dev, u64 mask)
398{
399 return 1;
400}
401
402struct dma_mapping_ops vio_dma_ops = {
403 .alloc_coherent = vio_alloc_coherent,
404 .free_coherent = vio_free_coherent,
405 .map_single = vio_map_single,
406 .unmap_single = vio_unmap_single,
407 .map_sg = vio_map_sg,
408 .unmap_sg = vio_unmap_sg,
409 .dma_supported = vio_dma_supported,
410};
411
412static int vio_bus_match(struct device *dev, struct device_driver *drv) 359static int vio_bus_match(struct device *dev, struct device_driver *drv)
413{ 360{
414 const struct vio_dev *vio_dev = to_vio_dev(dev); 361 const struct vio_dev *vio_dev = to_vio_dev(dev);
@@ -422,13 +369,14 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
422 char *buffer, int buffer_size) 369 char *buffer, int buffer_size)
423{ 370{
424 const struct vio_dev *vio_dev = to_vio_dev(dev); 371 const struct vio_dev *vio_dev = to_vio_dev(dev);
425 struct device_node *dn = dev->platform_data; 372 struct device_node *dn;
426 const char *cp; 373 const char *cp;
427 int length; 374 int length;
428 375
429 if (!num_envp) 376 if (!num_envp)
430 return -ENOMEM; 377 return -ENOMEM;
431 378
379 dn = dev->archdata.of_node;
432 if (!dn) 380 if (!dn)
433 return -ENODEV; 381 return -ENODEV;
434 cp = get_property(dn, "compatible", &length); 382 cp = get_property(dn, "compatible", &length);
@@ -465,7 +413,7 @@ struct bus_type vio_bus_type = {
465*/ 413*/
466const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) 414const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
467{ 415{
468 return get_property(vdev->dev.platform_data, which, length); 416 return get_property(vdev->dev.archdata.of_node, which, length);
469} 417}
470EXPORT_SYMBOL(vio_get_attribute); 418EXPORT_SYMBOL(vio_get_attribute);
471 419