diff options
26 files changed, 451 insertions, 611 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 | |||
62 | module-$(CONFIG_PPC64) += module_64.o | 62 | module-$(CONFIG_PPC64) += module_64.o |
63 | obj-$(CONFIG_MODULES) += $(module-y) | 63 | obj-$(CONFIG_MODULES) += $(module-y) |
64 | 64 | ||
65 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | 65 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o |
66 | pci_direct_iommu.o iomap.o | ||
67 | pci32-$(CONFIG_PPC32) := pci_32.o | 66 | pci32-$(CONFIG_PPC32) := pci_32.o |
68 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 67 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) |
69 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 68 | kexec-$(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 | ||
17 | static 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 | ||
34 | int dma_supported(struct device *dev, u64 mask) | 18 | static 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 | */ | ||
31 | static 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 | } |
42 | EXPORT_SYMBOL(dma_supported); | ||
43 | 38 | ||
44 | int dma_set_mask(struct device *dev, u64 dma_mask) | 39 | static 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 | } |
61 | EXPORT_SYMBOL(dma_set_mask); | ||
62 | 44 | ||
63 | void *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 | */ | ||
51 | static 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 | } |
72 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
73 | 58 | ||
74 | void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 59 | |
75 | dma_addr_t dma_handle) | 60 | static 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); | 68 | static 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 | } |
83 | EXPORT_SYMBOL(dma_free_coherent); | ||
84 | 74 | ||
85 | dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, | 75 | static 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 | } |
94 | EXPORT_SYMBOL(dma_map_single); | ||
95 | 80 | ||
96 | void 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) | 82 | static 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 | } |
105 | EXPORT_SYMBOL(dma_unmap_single); | ||
106 | 100 | ||
107 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 101 | struct 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 | }; | ||
110 | EXPORT_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, | 116 | static 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 | } |
118 | EXPORT_SYMBOL(dma_map_page); | ||
119 | 129 | ||
120 | void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | 130 | static 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); | 136 | static 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); | 143 | static 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 | } |
129 | EXPORT_SYMBOL(dma_unmap_page); | ||
130 | 148 | ||
131 | int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | 149 | static 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 | } |
140 | EXPORT_SYMBOL(dma_map_sg); | ||
141 | 161 | ||
142 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | 162 | static 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); | 167 | static 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 | } |
151 | EXPORT_SYMBOL(dma_unmap_sg); | 175 | |
176 | struct 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 | }; | ||
185 | EXPORT_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 | ||
115 | struct dma_mapping_ops ibmebus_dma_ops = { | 115 | static 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 | ||
261 | int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | 261 | int 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 | ||
62 | LIST_HEAD(hose_list); | 62 | LIST_HEAD(hose_list); |
63 | 63 | ||
64 | struct dma_mapping_ops pci_dma_ops; | 64 | struct dma_mapping_ops *pci_dma_ops; |
65 | EXPORT_SYMBOL(pci_dma_ops); | 65 | EXPORT_SYMBOL(pci_dma_ops); |
66 | 66 | ||
67 | int global_phb_number; /* Global phb counter */ | 67 | int global_phb_number; /* Global phb counter */ |
@@ -1205,15 +1205,35 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | |||
1205 | } | 1205 | } |
1206 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 1206 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
1207 | 1207 | ||
1208 | void __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 | } | ||
1226 | EXPORT_SYMBOL(pcibios_setup_new_device); | ||
1208 | 1227 | ||
1209 | static void __devinit do_bus_setup(struct pci_bus *bus) | 1228 | static 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 | |||
32 | static 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 | |||
45 | static 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 | |||
51 | static 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 | |||
57 | static 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 | |||
62 | static 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 | |||
75 | static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg, | ||
76 | int nents, enum dma_data_direction direction) | ||
77 | { | ||
78 | } | ||
79 | |||
80 | static int pci_direct_dma_supported(struct device *dev, u64 mask) | ||
81 | { | ||
82 | return mask < 0x100000000ull; | ||
83 | } | ||
84 | |||
85 | static 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 | |||
95 | void __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 | |||
47 | static 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 | |||
62 | static 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 | */ | ||
85 | static 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 | |||
93 | static 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 | */ | ||
105 | static 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 | |||
113 | static 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 | |||
120 | static 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 | |||
127 | static 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 */ | ||
134 | static 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 | |||
151 | struct 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 | |||
161 | void 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 */ |
199 | static void __devinit vio_dev_release(struct device *dev) | 200 | static 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, | |||
336 | static ssize_t devspec_show(struct device *dev, | 339 | static 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 | } |
354 | EXPORT_SYMBOL(vio_unregister_device); | 357 | EXPORT_SYMBOL(vio_unregister_device); |
355 | 358 | ||
356 | static 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 | |||
363 | static 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 | |||
370 | static 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 | |||
377 | static 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 | |||
383 | static 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 | |||
390 | static 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 | |||
397 | static int vio_dma_supported(struct device *dev, u64 mask) | ||
398 | { | ||
399 | return 1; | ||
400 | } | ||
401 | |||
402 | struct 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 | |||
412 | static int vio_bus_match(struct device *dev, struct device_driver *drv) | 359 | static 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 | */ |
466 | const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) | 414 | const 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 | } |
470 | EXPORT_SYMBOL(vio_get_attribute); | 418 | EXPORT_SYMBOL(vio_get_attribute); |
471 | 419 | ||
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index aca4c3db0dde..0e6ab8a55ef7 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -255,9 +255,6 @@ static void enable_mapping(void __iomem *base, void __iomem *mmio_base) | |||
255 | set_iost_origin(mmio_base); | 255 | set_iost_origin(mmio_base); |
256 | } | 256 | } |
257 | 257 | ||
258 | static void iommu_dev_setup_null(struct pci_dev *d) { } | ||
259 | static void iommu_bus_setup_null(struct pci_bus *b) { } | ||
260 | |||
261 | struct cell_iommu { | 258 | struct cell_iommu { |
262 | unsigned long base; | 259 | unsigned long base; |
263 | unsigned long mmio_base; | 260 | unsigned long mmio_base; |
@@ -306,12 +303,15 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, | |||
306 | } | 303 | } |
307 | } | 304 | } |
308 | 305 | ||
309 | static void iommu_devnode_setup(struct device_node *d) | 306 | static void pci_dma_cell_bus_setup(struct pci_bus *b) |
310 | { | 307 | { |
311 | const unsigned int *ioid; | 308 | const unsigned int *ioid; |
312 | unsigned long map_start, map_size, token; | 309 | unsigned long map_start, map_size, token; |
313 | const unsigned long *dma_window; | 310 | const unsigned long *dma_window; |
314 | struct cell_iommu *iommu; | 311 | struct cell_iommu *iommu; |
312 | struct device_node *d; | ||
313 | |||
314 | d = pci_bus_to_OF_node(b); | ||
315 | 315 | ||
316 | ioid = get_property(d, "ioid", NULL); | 316 | ioid = get_property(d, "ioid", NULL); |
317 | if (!ioid) | 317 | if (!ioid) |
@@ -330,12 +330,6 @@ static void iommu_devnode_setup(struct device_node *d) | |||
330 | cell_do_map_iommu(iommu, *ioid, map_start, map_size); | 330 | cell_do_map_iommu(iommu, *ioid, map_start, map_size); |
331 | } | 331 | } |
332 | 332 | ||
333 | static void iommu_bus_setup(struct pci_bus *b) | ||
334 | { | ||
335 | struct device_node *d = (struct device_node *)b->sysdata; | ||
336 | iommu_devnode_setup(d); | ||
337 | } | ||
338 | |||
339 | 333 | ||
340 | static int cell_map_iommu_hardcoded(int num_nodes) | 334 | static int cell_map_iommu_hardcoded(int num_nodes) |
341 | { | 335 | { |
@@ -499,16 +493,13 @@ void cell_init_iommu(void) | |||
499 | 493 | ||
500 | if (setup_bus) { | 494 | if (setup_bus) { |
501 | pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__); | 495 | pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__); |
502 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 496 | ppc_md.pci_dma_bus_setup = pci_dma_cell_bus_setup; |
503 | ppc_md.iommu_bus_setup = iommu_bus_setup; | ||
504 | } else { | 497 | } else { |
505 | pr_debug("%s: IOMMU mapping activated, " | 498 | pr_debug("%s: IOMMU mapping activated, " |
506 | "no device action necessary\n", __FUNCTION__); | 499 | "no device action necessary\n", __FUNCTION__); |
507 | /* Direct I/O, IOMMU off */ | 500 | /* Direct I/O, IOMMU off */ |
508 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | ||
509 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | ||
510 | } | 501 | } |
511 | } | 502 | } |
512 | 503 | ||
513 | pci_dma_ops = cell_iommu_ops; | 504 | pci_dma_ops = &cell_iommu_ops; |
514 | } | 505 | } |
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 218817d13c5c..ee0a4e42e4f0 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
30 | #include <linux/pci.h> | ||
30 | 31 | ||
31 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
32 | #include <asm/tce.h> | 33 | #include <asm/tce.h> |
@@ -168,7 +169,7 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) | |||
168 | } | 169 | } |
169 | 170 | ||
170 | 171 | ||
171 | void iommu_devnode_init_iSeries(struct device_node *dn) | 172 | void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) |
172 | { | 173 | { |
173 | struct iommu_table *tbl; | 174 | struct iommu_table *tbl; |
174 | struct pci_dn *pdn = PCI_DN(dn); | 175 | struct pci_dn *pdn = PCI_DN(dn); |
@@ -186,19 +187,14 @@ void iommu_devnode_init_iSeries(struct device_node *dn) | |||
186 | pdn->iommu_table = iommu_init_table(tbl, -1); | 187 | pdn->iommu_table = iommu_init_table(tbl, -1); |
187 | else | 188 | else |
188 | kfree(tbl); | 189 | kfree(tbl); |
190 | pdev->dev.archdata.dma_data = pdn->iommu_table; | ||
189 | } | 191 | } |
190 | #endif | 192 | #endif |
191 | 193 | ||
192 | static void iommu_dev_setup_iSeries(struct pci_dev *dev) { } | ||
193 | static void iommu_bus_setup_iSeries(struct pci_bus *bus) { } | ||
194 | |||
195 | void iommu_init_early_iSeries(void) | 194 | void iommu_init_early_iSeries(void) |
196 | { | 195 | { |
197 | ppc_md.tce_build = tce_build_iSeries; | 196 | ppc_md.tce_build = tce_build_iSeries; |
198 | ppc_md.tce_free = tce_free_iSeries; | 197 | ppc_md.tce_free = tce_free_iSeries; |
199 | 198 | ||
200 | ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries; | 199 | pci_dma_ops = &dma_iommu_ops; |
201 | ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries; | ||
202 | |||
203 | pci_iommu_init(); | ||
204 | } | 200 | } |
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4aa165e010d9..a90ae42a7bc2 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -253,7 +253,7 @@ void __init iSeries_pci_final_fixup(void) | |||
253 | PCI_DN(node)->pcidev = pdev; | 253 | PCI_DN(node)->pcidev = pdev; |
254 | allocate_device_bars(pdev); | 254 | allocate_device_bars(pdev); |
255 | iSeries_Device_Information(pdev, DeviceCount); | 255 | iSeries_Device_Information(pdev, DeviceCount); |
256 | iommu_devnode_init_iSeries(node); | 256 | iommu_devnode_init_iSeries(pdev, node); |
257 | } else | 257 | } else |
258 | printk("PCI: Device Tree not found for 0x%016lX\n", | 258 | printk("PCI: Device Tree not found for 0x%016lX\n", |
259 | (unsigned long)pdev); | 259 | (unsigned long)pdev); |
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index eb2457567f8a..89d6e295dbf7 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/pci.h> | ||
29 | 30 | ||
30 | #include <asm/prom.h> | 31 | #include <asm/prom.h> |
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -71,6 +72,9 @@ void __init pas_setup_arch(void) | |||
71 | /* Setup SMP callback */ | 72 | /* Setup SMP callback */ |
72 | smp_ops = &pas_smp_ops; | 73 | smp_ops = &pas_smp_ops; |
73 | #endif | 74 | #endif |
75 | /* no iommu yet */ | ||
76 | pci_dma_ops = &dma_direct_ops; | ||
77 | |||
74 | /* Lookup PCI hosts */ | 78 | /* Lookup PCI hosts */ |
75 | pas_pci_init(); | 79 | pas_pci_init(); |
76 | 80 | ||
@@ -81,17 +85,6 @@ void __init pas_setup_arch(void) | |||
81 | printk(KERN_DEBUG "Using default idle loop\n"); | 85 | printk(KERN_DEBUG "Using default idle loop\n"); |
82 | } | 86 | } |
83 | 87 | ||
84 | static void iommu_dev_setup_null(struct pci_dev *dev) { } | ||
85 | static void iommu_bus_setup_null(struct pci_bus *bus) { } | ||
86 | |||
87 | static void __init pas_init_early(void) | ||
88 | { | ||
89 | /* No iommu code yet */ | ||
90 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | ||
91 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | ||
92 | pci_direct_iommu_init(); | ||
93 | } | ||
94 | |||
95 | /* No legacy IO on our parts */ | 88 | /* No legacy IO on our parts */ |
96 | static int pas_check_legacy_ioport(unsigned int baseport) | 89 | static int pas_check_legacy_ioport(unsigned int baseport) |
97 | { | 90 | { |
@@ -173,7 +166,6 @@ define_machine(pas) { | |||
173 | .name = "PA Semi PA6T-1682M", | 166 | .name = "PA Semi PA6T-1682M", |
174 | .probe = pas_probe, | 167 | .probe = pas_probe, |
175 | .setup_arch = pas_setup_arch, | 168 | .setup_arch = pas_setup_arch, |
176 | .init_early = pas_init_early, | ||
177 | .init_IRQ = pas_init_IRQ, | 169 | .init_IRQ = pas_init_IRQ, |
178 | .get_irq = mpic_get_irq, | 170 | .get_irq = mpic_get_irq, |
179 | .restart = pas_restart, | 171 | .restart = pas_restart, |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 556c279a789d..3c95392f4f41 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; | 309 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
310 | } | 310 | } |
311 | 311 | ||
312 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 312 | static void pci_dma_bus_setup_pSeries(struct pci_bus *bus) |
313 | { | 313 | { |
314 | struct device_node *dn; | 314 | struct device_node *dn; |
315 | struct iommu_table *tbl; | 315 | struct iommu_table *tbl; |
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
318 | struct pci_dn *pci; | 318 | struct pci_dn *pci; |
319 | int children; | 319 | int children; |
320 | 320 | ||
321 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | ||
322 | |||
323 | dn = pci_bus_to_OF_node(bus); | 321 | dn = pci_bus_to_OF_node(bus); |
324 | pci = PCI_DN(dn); | 322 | |
323 | DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name); | ||
325 | 324 | ||
326 | if (bus->self) { | 325 | if (bus->self) { |
327 | /* This is not a root bus, any setup will be done for the | 326 | /* This is not a root bus, any setup will be done for the |
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
329 | */ | 328 | */ |
330 | return; | 329 | return; |
331 | } | 330 | } |
331 | pci = PCI_DN(dn); | ||
332 | 332 | ||
333 | /* Check if the ISA bus on the system is under | 333 | /* Check if the ISA bus on the system is under |
334 | * this PHB. | 334 | * this PHB. |
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) | |||
390 | } | 390 | } |
391 | 391 | ||
392 | 392 | ||
393 | static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | 393 | static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) |
394 | { | 394 | { |
395 | struct iommu_table *tbl; | 395 | struct iommu_table *tbl; |
396 | struct device_node *dn, *pdn; | 396 | struct device_node *dn, *pdn; |
397 | struct pci_dn *ppci; | 397 | struct pci_dn *ppci; |
398 | const void *dma_window = NULL; | 398 | const void *dma_window = NULL; |
399 | 399 | ||
400 | DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); | ||
401 | |||
402 | dn = pci_bus_to_OF_node(bus); | 400 | dn = pci_bus_to_OF_node(bus); |
403 | 401 | ||
402 | DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name); | ||
403 | |||
404 | /* Find nearest ibm,dma-window, walking up the device tree */ | 404 | /* Find nearest ibm,dma-window, walking up the device tree */ |
405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { | 405 | for (pdn = dn; pdn != NULL; pdn = pdn->parent) { |
406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); | 406 | dma_window = get_property(pdn, "ibm,dma-window", NULL); |
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
409 | } | 409 | } |
410 | 410 | ||
411 | if (dma_window == NULL) { | 411 | if (dma_window == NULL) { |
412 | DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name); | 412 | DBG(" no ibm,dma-window property !\n"); |
413 | return; | 413 | return; |
414 | } | 414 | } |
415 | 415 | ||
416 | ppci = PCI_DN(pdn); | 416 | ppci = PCI_DN(pdn); |
417 | |||
418 | DBG(" parent is %s, iommu_table: 0x%p\n", | ||
419 | pdn->full_name, ppci->iommu_table); | ||
420 | |||
417 | if (!ppci->iommu_table) { | 421 | if (!ppci->iommu_table) { |
418 | /* Bussubno hasn't been copied yet. | 422 | /* Bussubno hasn't been copied yet. |
419 | * Do it now because iommu_table_setparms_lpar needs it. | 423 | * Do it now because iommu_table_setparms_lpar needs it. |
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
427 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); | 431 | iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); |
428 | 432 | ||
429 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); | 433 | ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); |
434 | DBG(" created table: %p\n", ppci->iommu_table); | ||
430 | } | 435 | } |
431 | 436 | ||
432 | if (pdn != dn) | 437 | if (pdn != dn) |
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
434 | } | 439 | } |
435 | 440 | ||
436 | 441 | ||
437 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 442 | static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) |
438 | { | 443 | { |
439 | struct device_node *dn, *mydn; | 444 | struct device_node *dn; |
440 | struct iommu_table *tbl; | 445 | struct iommu_table *tbl; |
441 | 446 | ||
442 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev)); | 447 | DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev)); |
443 | 448 | ||
444 | mydn = dn = pci_device_to_OF_node(dev); | 449 | dn = dev->dev.archdata.of_node; |
445 | 450 | ||
446 | /* If we're the direct child of a root bus, then we need to allocate | 451 | /* If we're the direct child of a root bus, then we need to allocate |
447 | * an iommu table ourselves. The bus setup code should have setup | 452 | * an iommu table ourselves. The bus setup code should have setup |
448 | * the window sizes already. | 453 | * the window sizes already. |
449 | */ | 454 | */ |
450 | if (!dev->bus->self) { | 455 | if (!dev->bus->self) { |
456 | struct pci_controller *phb = PCI_DN(dn)->phb; | ||
457 | |||
451 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | 458 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); |
452 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, | 459 | tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, |
453 | PCI_DN(dn)->phb->node); | 460 | phb->node); |
454 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | 461 | iommu_table_setparms(phb, dn, tbl); |
455 | PCI_DN(dn)->iommu_table = iommu_init_table(tbl, | 462 | dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node); |
456 | PCI_DN(dn)->phb->node); | ||
457 | |||
458 | return; | 463 | return; |
459 | } | 464 | } |
460 | 465 | ||
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) | |||
465 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) | 470 | while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL) |
466 | dn = dn->parent; | 471 | dn = dn->parent; |
467 | 472 | ||
468 | if (dn && PCI_DN(dn)) { | 473 | if (dn && PCI_DN(dn)) |
469 | PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table; | 474 | dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table; |
470 | } else { | 475 | else |
471 | DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev)); | 476 | printk(KERN_WARNING "iommu: Device %s has no iommu table\n", |
472 | } | 477 | pci_name(dev)); |
473 | } | 478 | } |
474 | 479 | ||
475 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | 480 | static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) |
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = { | |||
495 | .notifier_call = iommu_reconfig_notifier, | 500 | .notifier_call = iommu_reconfig_notifier, |
496 | }; | 501 | }; |
497 | 502 | ||
498 | static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | 503 | static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) |
499 | { | 504 | { |
500 | struct device_node *pdn, *dn; | 505 | struct device_node *pdn, *dn; |
501 | struct iommu_table *tbl; | 506 | struct iommu_table *tbl; |
502 | const void *dma_window = NULL; | 507 | const void *dma_window = NULL; |
503 | struct pci_dn *pci; | 508 | struct pci_dn *pci; |
504 | 509 | ||
510 | DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); | ||
511 | |||
505 | /* dev setup for LPAR is a little tricky, since the device tree might | 512 | /* dev setup for LPAR is a little tricky, since the device tree might |
506 | * contain the dma-window properties per-device and not neccesarily | 513 | * contain the dma-window properties per-device and not neccesarily |
507 | * for the bus. So we need to search upwards in the tree until we | 514 | * for the bus. So we need to search upwards in the tree until we |
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
509 | * already allocated. | 516 | * already allocated. |
510 | */ | 517 | */ |
511 | dn = pci_device_to_OF_node(dev); | 518 | dn = pci_device_to_OF_node(dev); |
512 | 519 | DBG(" node is %s\n", dn->full_name); | |
513 | DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n", | ||
514 | dev, pci_name(dev), dn->full_name); | ||
515 | 520 | ||
516 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; | 521 | for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; |
517 | pdn = pdn->parent) { | 522 | pdn = pdn->parent) { |
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
520 | break; | 525 | break; |
521 | } | 526 | } |
522 | 527 | ||
528 | DBG(" parent is %s\n", pdn->full_name); | ||
529 | |||
523 | /* Check for parent == NULL so we don't try to setup the empty EADS | 530 | /* Check for parent == NULL so we don't try to setup the empty EADS |
524 | * slots on POWER4 machines. | 531 | * slots on POWER4 machines. |
525 | */ | 532 | */ |
526 | if (dma_window == NULL || pdn->parent == NULL) { | 533 | if (dma_window == NULL || pdn->parent == NULL) { |
527 | DBG("No dma window for device, linking to parent\n"); | 534 | DBG(" no dma window for device, linking to parent\n"); |
528 | PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table; | 535 | dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table; |
529 | return; | 536 | return; |
530 | } else { | ||
531 | DBG("Found DMA window, allocating table\n"); | ||
532 | } | 537 | } |
538 | DBG(" found DMA window, table: %p\n", pci->iommu_table); | ||
533 | 539 | ||
534 | pci = PCI_DN(pdn); | 540 | pci = PCI_DN(pdn); |
535 | if (!pci->iommu_table) { | 541 | if (!pci->iommu_table) { |
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) | |||
542 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); | 548 | iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); |
543 | 549 | ||
544 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); | 550 | pci->iommu_table = iommu_init_table(tbl, pci->phb->node); |
551 | DBG(" created table: %p\n", pci->iommu_table); | ||
545 | } | 552 | } |
546 | 553 | ||
547 | if (pdn != dn) | 554 | dev->dev.archdata.dma_data = pci->iommu_table; |
548 | PCI_DN(dn)->iommu_table = pci->iommu_table; | ||
549 | } | 555 | } |
550 | 556 | ||
551 | static void iommu_bus_setup_null(struct pci_bus *b) { } | ||
552 | static void iommu_dev_setup_null(struct pci_dev *d) { } | ||
553 | |||
554 | /* These are called very early. */ | 557 | /* These are called very early. */ |
555 | void iommu_init_early_pSeries(void) | 558 | void iommu_init_early_pSeries(void) |
556 | { | 559 | { |
557 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { | 560 | if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) { |
558 | /* Direct I/O, IOMMU off */ | 561 | /* Direct I/O, IOMMU off */ |
559 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 562 | ppc_md.pci_dma_dev_setup = NULL; |
560 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 563 | ppc_md.pci_dma_bus_setup = NULL; |
561 | pci_direct_iommu_init(); | 564 | pci_dma_ops = &dma_direct_ops; |
562 | |||
563 | return; | 565 | return; |
564 | } | 566 | } |
565 | 567 | ||
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void) | |||
572 | ppc_md.tce_free = tce_free_pSeriesLP; | 574 | ppc_md.tce_free = tce_free_pSeriesLP; |
573 | } | 575 | } |
574 | ppc_md.tce_get = tce_get_pSeriesLP; | 576 | ppc_md.tce_get = tce_get_pSeriesLP; |
575 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP; | 577 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP; |
576 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP; | 578 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP; |
577 | } else { | 579 | } else { |
578 | ppc_md.tce_build = tce_build_pSeries; | 580 | ppc_md.tce_build = tce_build_pSeries; |
579 | ppc_md.tce_free = tce_free_pSeries; | 581 | ppc_md.tce_free = tce_free_pSeries; |
580 | ppc_md.tce_get = tce_get_pseries; | 582 | ppc_md.tce_get = tce_get_pseries; |
581 | ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries; | 583 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries; |
582 | ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries; | 584 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries; |
583 | } | 585 | } |
584 | 586 | ||
585 | 587 | ||
586 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); | 588 | pSeries_reconfig_notifier_register(&iommu_reconfig_nb); |
587 | 589 | ||
588 | pci_iommu_init(); | 590 | pci_dma_ops = &dma_iommu_ops; |
589 | } | 591 | } |
590 | 592 | ||
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 6bfacc217085..bb0cb5c5b565 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
93 | if (list_empty(&dev->global_list)) { | 93 | if (list_empty(&dev->global_list)) { |
94 | int i; | 94 | int i; |
95 | 95 | ||
96 | /* Need to setup IOMMU tables */ | 96 | /* Fill device archdata and setup iommu table */ |
97 | ppc_md.iommu_dev_setup(dev); | 97 | pcibios_setup_new_device(dev); |
98 | 98 | ||
99 | if(fix_bus) | 99 | if(fix_bus) |
100 | pcibios_fixup_device_resources(dev, bus); | 100 | pcibios_fixup_device_resources(dev, bus); |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 572b7846cc77..ac784bb57289 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -289,24 +289,15 @@ static void iommu_table_dart_setup(void) | |||
289 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); | 289 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); |
290 | } | 290 | } |
291 | 291 | ||
292 | static void iommu_dev_setup_dart(struct pci_dev *dev) | 292 | static void pci_dma_dev_setup_dart(struct pci_dev *dev) |
293 | { | 293 | { |
294 | struct device_node *dn; | ||
295 | |||
296 | /* We only have one iommu table on the mac for now, which makes | 294 | /* We only have one iommu table on the mac for now, which makes |
297 | * things simple. Setup all PCI devices to point to this table | 295 | * things simple. Setup all PCI devices to point to this table |
298 | * | ||
299 | * We must use pci_device_to_OF_node() to make sure that | ||
300 | * we get the real "final" pointer to the device in the | ||
301 | * pci_dev sysdata and not the temporary PHB one | ||
302 | */ | 296 | */ |
303 | dn = pci_device_to_OF_node(dev); | 297 | dev->dev.archdata.dma_data = &iommu_table_dart; |
304 | |||
305 | if (dn) | ||
306 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | ||
307 | } | 298 | } |
308 | 299 | ||
309 | static void iommu_bus_setup_dart(struct pci_bus *bus) | 300 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) |
310 | { | 301 | { |
311 | struct device_node *dn; | 302 | struct device_node *dn; |
312 | 303 | ||
@@ -321,9 +312,6 @@ static void iommu_bus_setup_dart(struct pci_bus *bus) | |||
321 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | 312 | PCI_DN(dn)->iommu_table = &iommu_table_dart; |
322 | } | 313 | } |
323 | 314 | ||
324 | static void iommu_dev_setup_null(struct pci_dev *dev) { } | ||
325 | static void iommu_bus_setup_null(struct pci_bus *bus) { } | ||
326 | |||
327 | void iommu_init_early_dart(void) | 315 | void iommu_init_early_dart(void) |
328 | { | 316 | { |
329 | struct device_node *dn; | 317 | struct device_node *dn; |
@@ -344,22 +332,21 @@ void iommu_init_early_dart(void) | |||
344 | 332 | ||
345 | /* Initialize the DART HW */ | 333 | /* Initialize the DART HW */ |
346 | if (dart_init(dn) == 0) { | 334 | if (dart_init(dn) == 0) { |
347 | ppc_md.iommu_dev_setup = iommu_dev_setup_dart; | 335 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; |
348 | ppc_md.iommu_bus_setup = iommu_bus_setup_dart; | 336 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; |
349 | 337 | ||
350 | /* Setup pci_dma ops */ | 338 | /* Setup pci_dma ops */ |
351 | pci_iommu_init(); | 339 | pci_dma_ops = &dma_iommu_ops; |
352 | |||
353 | return; | 340 | return; |
354 | } | 341 | } |
355 | 342 | ||
356 | bail: | 343 | bail: |
357 | /* If init failed, use direct iommu and null setup functions */ | 344 | /* If init failed, use direct iommu and null setup functions */ |
358 | ppc_md.iommu_dev_setup = iommu_dev_setup_null; | 345 | ppc_md.pci_dma_dev_setup = NULL; |
359 | ppc_md.iommu_bus_setup = iommu_bus_setup_null; | 346 | ppc_md.pci_dma_bus_setup = NULL; |
360 | 347 | ||
361 | /* Setup pci_dma ops */ | 348 | /* Setup pci_dma ops */ |
362 | pci_direct_iommu_init(); | 349 | pci_dma_ops = &dma_direct_ops; |
363 | } | 350 | } |
364 | 351 | ||
365 | 352 | ||
diff --git a/include/asm-powerpc/device.h b/include/asm-powerpc/device.h index d8f9872b0e2d..228ab2a315b9 100644 --- a/include/asm-powerpc/device.h +++ b/include/asm-powerpc/device.h | |||
@@ -3,5 +3,22 @@ | |||
3 | * | 3 | * |
4 | * This file is released under the GPLv2 | 4 | * This file is released under the GPLv2 |
5 | */ | 5 | */ |
6 | #include <asm-generic/device.h> | 6 | #ifndef _ASM_POWERPC_DEVICE_H |
7 | #define _ASM_POWERPC_DEVICE_H | ||
7 | 8 | ||
9 | struct dma_mapping_ops; | ||
10 | struct device_node; | ||
11 | |||
12 | struct dev_archdata { | ||
13 | /* Optional pointer to an OF device node */ | ||
14 | struct device_node *of_node; | ||
15 | |||
16 | /* DMA operations on that device */ | ||
17 | struct dma_mapping_ops *dma_ops; | ||
18 | void *dma_data; | ||
19 | |||
20 | /* NUMA node if applicable */ | ||
21 | int numa_node; | ||
22 | }; | ||
23 | |||
24 | #endif /* _ASM_POWERPC_DEVICE_H */ | ||
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h index 2ab9baf78bb4..8367810c994c 100644 --- a/include/asm-powerpc/dma-mapping.h +++ b/include/asm-powerpc/dma-mapping.h | |||
@@ -44,26 +44,148 @@ extern void __dma_sync_page(struct page *page, unsigned long offset, | |||
44 | #endif /* ! CONFIG_NOT_COHERENT_CACHE */ | 44 | #endif /* ! CONFIG_NOT_COHERENT_CACHE */ |
45 | 45 | ||
46 | #ifdef CONFIG_PPC64 | 46 | #ifdef CONFIG_PPC64 |
47 | /* | ||
48 | * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO | ||
49 | */ | ||
50 | struct dma_mapping_ops { | ||
51 | void * (*alloc_coherent)(struct device *dev, size_t size, | ||
52 | dma_addr_t *dma_handle, gfp_t flag); | ||
53 | void (*free_coherent)(struct device *dev, size_t size, | ||
54 | void *vaddr, dma_addr_t dma_handle); | ||
55 | dma_addr_t (*map_single)(struct device *dev, void *ptr, | ||
56 | size_t size, enum dma_data_direction direction); | ||
57 | void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, | ||
58 | size_t size, enum dma_data_direction direction); | ||
59 | int (*map_sg)(struct device *dev, struct scatterlist *sg, | ||
60 | int nents, enum dma_data_direction direction); | ||
61 | void (*unmap_sg)(struct device *dev, struct scatterlist *sg, | ||
62 | int nents, enum dma_data_direction direction); | ||
63 | int (*dma_supported)(struct device *dev, u64 mask); | ||
64 | int (*dac_dma_supported)(struct device *dev, u64 mask); | ||
65 | int (*set_dma_mask)(struct device *dev, u64 dma_mask); | ||
66 | }; | ||
67 | |||
68 | static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) | ||
69 | { | ||
70 | /* We don't handle the NULL dev case for ISA for now. We could | ||
71 | * do it via an out of line call but it is not needed for now. The | ||
72 | * only ISA DMA device we support is the floppy and we have a hack | ||
73 | * in the floppy driver directly to get a device for us. | ||
74 | */ | ||
75 | if (unlikely(dev == NULL || dev->archdata.dma_ops == NULL)) | ||
76 | return NULL; | ||
77 | return dev->archdata.dma_ops; | ||
78 | } | ||
79 | |||
80 | static inline int dma_supported(struct device *dev, u64 mask) | ||
81 | { | ||
82 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
83 | |||
84 | if (unlikely(dma_ops == NULL)) | ||
85 | return 0; | ||
86 | if (dma_ops->dma_supported == NULL) | ||
87 | return 1; | ||
88 | return dma_ops->dma_supported(dev, mask); | ||
89 | } | ||
90 | |||
91 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | ||
92 | { | ||
93 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
94 | |||
95 | if (unlikely(dma_ops == NULL)) | ||
96 | return -EIO; | ||
97 | if (dma_ops->set_dma_mask != NULL) | ||
98 | return dma_ops->set_dma_mask(dev, dma_mask); | ||
99 | if (!dev->dma_mask || !dma_supported(dev, *dev->dma_mask)) | ||
100 | return -EIO; | ||
101 | *dev->dma_mask = dma_mask; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | ||
106 | dma_addr_t *dma_handle, gfp_t flag) | ||
107 | { | ||
108 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
109 | |||
110 | BUG_ON(!dma_ops); | ||
111 | return dma_ops->alloc_coherent(dev, size, dma_handle, flag); | ||
112 | } | ||
113 | |||
114 | static inline void dma_free_coherent(struct device *dev, size_t size, | ||
115 | void *cpu_addr, dma_addr_t dma_handle) | ||
116 | { | ||
117 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
118 | |||
119 | BUG_ON(!dma_ops); | ||
120 | dma_ops->free_coherent(dev, size, cpu_addr, dma_handle); | ||
121 | } | ||
122 | |||
123 | static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
124 | size_t size, | ||
125 | enum dma_data_direction direction) | ||
126 | { | ||
127 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
128 | |||
129 | BUG_ON(!dma_ops); | ||
130 | return dma_ops->map_single(dev, cpu_addr, size, direction); | ||
131 | } | ||
132 | |||
133 | static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
134 | size_t size, | ||
135 | enum dma_data_direction direction) | ||
136 | { | ||
137 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
138 | |||
139 | BUG_ON(!dma_ops); | ||
140 | dma_ops->unmap_single(dev, dma_addr, size, direction); | ||
141 | } | ||
142 | |||
143 | static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
144 | unsigned long offset, size_t size, | ||
145 | enum dma_data_direction direction) | ||
146 | { | ||
147 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
148 | |||
149 | BUG_ON(!dma_ops); | ||
150 | return dma_ops->map_single(dev, page_address(page) + offset, size, | ||
151 | direction); | ||
152 | } | ||
153 | |||
154 | static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
155 | size_t size, | ||
156 | enum dma_data_direction direction) | ||
157 | { | ||
158 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
159 | |||
160 | BUG_ON(!dma_ops); | ||
161 | dma_ops->unmap_single(dev, dma_address, size, direction); | ||
162 | } | ||
163 | |||
164 | static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
165 | int nents, enum dma_data_direction direction) | ||
166 | { | ||
167 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
168 | |||
169 | BUG_ON(!dma_ops); | ||
170 | return dma_ops->map_sg(dev, sg, nents, direction); | ||
171 | } | ||
172 | |||
173 | static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
174 | int nhwentries, | ||
175 | enum dma_data_direction direction) | ||
176 | { | ||
177 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | ||
178 | |||
179 | BUG_ON(!dma_ops); | ||
180 | dma_ops->unmap_sg(dev, sg, nhwentries, direction); | ||
181 | } | ||
47 | 182 | ||
48 | extern int dma_supported(struct device *dev, u64 mask); | 183 | |
49 | extern int dma_set_mask(struct device *dev, u64 dma_mask); | 184 | /* |
50 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | 185 | * Available generic sets of operations |
51 | dma_addr_t *dma_handle, gfp_t flag); | 186 | */ |
52 | extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 187 | extern struct dma_mapping_ops dma_iommu_ops; |
53 | dma_addr_t dma_handle); | 188 | extern struct dma_mapping_ops dma_direct_ops; |
54 | extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
55 | size_t size, enum dma_data_direction direction); | ||
56 | extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
57 | size_t size, enum dma_data_direction direction); | ||
58 | extern dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
59 | unsigned long offset, size_t size, | ||
60 | enum dma_data_direction direction); | ||
61 | extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
62 | size_t size, enum dma_data_direction direction); | ||
63 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
64 | enum dma_data_direction direction); | ||
65 | extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
66 | int nhwentries, enum dma_data_direction direction); | ||
67 | 189 | ||
68 | #else /* CONFIG_PPC64 */ | 190 | #else /* CONFIG_PPC64 */ |
69 | 191 | ||
@@ -261,25 +383,5 @@ static inline void dma_cache_sync(void *vaddr, size_t size, | |||
261 | __dma_sync(vaddr, size, (int)direction); | 383 | __dma_sync(vaddr, size, (int)direction); |
262 | } | 384 | } |
263 | 385 | ||
264 | /* | ||
265 | * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO | ||
266 | */ | ||
267 | struct dma_mapping_ops { | ||
268 | void * (*alloc_coherent)(struct device *dev, size_t size, | ||
269 | dma_addr_t *dma_handle, gfp_t flag); | ||
270 | void (*free_coherent)(struct device *dev, size_t size, | ||
271 | void *vaddr, dma_addr_t dma_handle); | ||
272 | dma_addr_t (*map_single)(struct device *dev, void *ptr, | ||
273 | size_t size, enum dma_data_direction direction); | ||
274 | void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, | ||
275 | size_t size, enum dma_data_direction direction); | ||
276 | int (*map_sg)(struct device *dev, struct scatterlist *sg, | ||
277 | int nents, enum dma_data_direction direction); | ||
278 | void (*unmap_sg)(struct device *dev, struct scatterlist *sg, | ||
279 | int nents, enum dma_data_direction direction); | ||
280 | int (*dma_supported)(struct device *dev, u64 mask); | ||
281 | int (*dac_dma_supported)(struct device *dev, u64 mask); | ||
282 | }; | ||
283 | |||
284 | #endif /* __KERNEL__ */ | 386 | #endif /* __KERNEL__ */ |
285 | #endif /* _ASM_DMA_MAPPING_H */ | 387 | #endif /* _ASM_DMA_MAPPING_H */ |
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 3493429b70f5..66112114b8c5 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/mod_devicetable.h> | 44 | #include <linux/mod_devicetable.h> |
45 | #include <asm/of_device.h> | 45 | #include <asm/of_device.h> |
46 | 46 | ||
47 | extern struct dma_mapping_ops ibmebus_dma_ops; | ||
48 | extern struct bus_type ibmebus_bus_type; | 47 | extern struct bus_type ibmebus_bus_type; |
49 | 48 | ||
50 | struct ibmebus_dev { | 49 | struct ibmebus_dev { |
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h index 19e6f7e0a607..19403183dbbc 100644 --- a/include/asm-powerpc/iommu.h +++ b/include/asm-powerpc/iommu.h | |||
@@ -79,22 +79,22 @@ extern void iommu_free_table(struct device_node *dn); | |||
79 | extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, | 79 | extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, |
80 | int nid); | 80 | int nid); |
81 | 81 | ||
82 | extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | 82 | extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, |
83 | struct scatterlist *sglist, int nelems, unsigned long mask, | 83 | int nelems, unsigned long mask, |
84 | enum dma_data_direction direction); | 84 | enum dma_data_direction direction); |
85 | extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, | 85 | extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, |
86 | int nelems, enum dma_data_direction direction); | 86 | int nelems, enum dma_data_direction direction); |
87 | 87 | ||
88 | extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 88 | extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, |
89 | dma_addr_t *dma_handle, unsigned long mask, | 89 | dma_addr_t *dma_handle, unsigned long mask, |
90 | gfp_t flag, int node); | 90 | gfp_t flag, int node); |
91 | extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, | 91 | extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, |
92 | void *vaddr, dma_addr_t dma_handle); | 92 | void *vaddr, dma_addr_t dma_handle); |
93 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | 93 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, |
94 | size_t size, unsigned long mask, | 94 | size_t size, unsigned long mask, |
95 | enum dma_data_direction direction); | 95 | enum dma_data_direction direction); |
96 | extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, | 96 | extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, |
97 | size_t size, enum dma_data_direction direction); | 97 | size_t size, enum dma_data_direction direction); |
98 | 98 | ||
99 | extern void iommu_init_early_pSeries(void); | 99 | extern void iommu_init_early_pSeries(void); |
100 | extern void iommu_init_early_iSeries(void); | 100 | extern void iommu_init_early_iSeries(void); |
diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h index 0edbfe10cb37..6e323a13ac30 100644 --- a/include/asm-powerpc/iseries/iommu.h +++ b/include/asm-powerpc/iseries/iommu.h | |||
@@ -21,11 +21,13 @@ | |||
21 | * Boston, MA 02111-1307 USA | 21 | * Boston, MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | 23 | ||
24 | struct pci_dev; | ||
24 | struct device_node; | 25 | struct device_node; |
25 | struct iommu_table; | 26 | struct iommu_table; |
26 | 27 | ||
27 | /* Creates table for an individual device node */ | 28 | /* Creates table for an individual device node */ |
28 | extern void iommu_devnode_init_iSeries(struct device_node *dn); | 29 | extern void iommu_devnode_init_iSeries(struct pci_dev *pdev, |
30 | struct device_node *dn); | ||
29 | 31 | ||
30 | /* Get table parameters from HV */ | 32 | /* Get table parameters from HV */ |
31 | extern void iommu_table_getparms_iSeries(unsigned long busno, | 33 | extern void iommu_table_getparms_iSeries(unsigned long busno, |
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 162205f62641..ccc29744656e 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h | |||
@@ -84,8 +84,8 @@ struct machdep_calls { | |||
84 | unsigned long (*tce_get)(struct iommu_table *tbl, | 84 | unsigned long (*tce_get)(struct iommu_table *tbl, |
85 | long index); | 85 | long index); |
86 | void (*tce_flush)(struct iommu_table *tbl); | 86 | void (*tce_flush)(struct iommu_table *tbl); |
87 | void (*iommu_dev_setup)(struct pci_dev *dev); | 87 | void (*pci_dma_dev_setup)(struct pci_dev *dev); |
88 | void (*iommu_bus_setup)(struct pci_bus *bus); | 88 | void (*pci_dma_bus_setup)(struct pci_bus *bus); |
89 | #endif /* CONFIG_PPC64 */ | 89 | #endif /* CONFIG_PPC64 */ |
90 | 90 | ||
91 | int (*probe)(void); | 91 | int (*probe)(void); |
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index 1ef7e9edd1a7..a889b2005bf5 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h | |||
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | struct of_device | 15 | struct of_device |
16 | { | 16 | { |
17 | struct device_node *node; /* OF device node */ | 17 | struct device_node *node; /* to be obsoleted */ |
18 | u64 dma_mask; /* DMA mask */ | 18 | u64 dma_mask; /* DMA mask */ |
19 | struct device dev; /* Generic device interface */ | 19 | struct device dev; /* Generic device interface */ |
20 | }; | 20 | }; |
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index c77286051496..16f13319c769 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h | |||
@@ -70,15 +70,15 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) | |||
70 | */ | 70 | */ |
71 | #define PCI_DISABLE_MWI | 71 | #define PCI_DISABLE_MWI |
72 | 72 | ||
73 | extern struct dma_mapping_ops pci_dma_ops; | 73 | extern struct dma_mapping_ops *pci_dma_ops; |
74 | 74 | ||
75 | /* For DAC DMA, we currently don't support it by default, but | 75 | /* For DAC DMA, we currently don't support it by default, but |
76 | * we let 64-bit platforms override this. | 76 | * we let 64-bit platforms override this. |
77 | */ | 77 | */ |
78 | static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) | 78 | static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) |
79 | { | 79 | { |
80 | if (pci_dma_ops.dac_dma_supported) | 80 | if (pci_dma_ops && pci_dma_ops->dac_dma_supported) |
81 | return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask); | 81 | return pci_dma_ops->dac_dma_supported(&hwdev->dev, mask); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
@@ -210,6 +210,8 @@ extern int remap_bus_range(struct pci_bus *bus); | |||
210 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, | 210 | extern void pcibios_fixup_device_resources(struct pci_dev *dev, |
211 | struct pci_bus *bus); | 211 | struct pci_bus *bus); |
212 | 212 | ||
213 | extern void pcibios_setup_new_device(struct pci_dev *dev); | ||
214 | |||
213 | extern void pcibios_claim_one_bus(struct pci_bus *b); | 215 | extern void pcibios_claim_one_bus(struct pci_bus *b); |
214 | 216 | ||
215 | extern struct pci_controller *init_phb_dynamic(struct device_node *dn); | 217 | extern struct pci_controller *init_phb_dynamic(struct device_node *dn); |
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 4b51d42e1419..0117b544ecbc 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h | |||
@@ -45,7 +45,6 @@ struct iommu_table; | |||
45 | * The vio_dev structure is used to describe virtual I/O devices. | 45 | * The vio_dev structure is used to describe virtual I/O devices. |
46 | */ | 46 | */ |
47 | struct vio_dev { | 47 | struct vio_dev { |
48 | struct iommu_table *iommu_table; /* vio_map_* uses this */ | ||
49 | const char *name; | 48 | const char *name; |
50 | const char *type; | 49 | const char *type; |
51 | uint32_t unit_address; | 50 | uint32_t unit_address; |