aboutsummaryrefslogtreecommitdiffstats
path: root/include
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 /include
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 'include')
-rw-r--r--include/asm-powerpc/device.h19
-rw-r--r--include/asm-powerpc/dma-mapping.h180
-rw-r--r--include/asm-powerpc/ibmebus.h1
-rw-r--r--include/asm-powerpc/iommu.h20
-rw-r--r--include/asm-powerpc/iseries/iommu.h4
-rw-r--r--include/asm-powerpc/machdep.h4
-rw-r--r--include/asm-powerpc/of_device.h2
-rw-r--r--include/asm-powerpc/pci.h8
-rw-r--r--include/asm-powerpc/vio.h1
9 files changed, 180 insertions, 59 deletions
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
9struct dma_mapping_ops;
10struct device_node;
11
12struct 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 */
50struct 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
68static 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
80static 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
91static 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
105static 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
114static 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
123static 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
133static 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
143static 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
154static 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
164static 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
173static 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
48extern int dma_supported(struct device *dev, u64 mask); 183
49extern int dma_set_mask(struct device *dev, u64 dma_mask); 184/*
50extern 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 */
52extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, 187extern struct dma_mapping_ops dma_iommu_ops;
53 dma_addr_t dma_handle); 188extern struct dma_mapping_ops dma_direct_ops;
54extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
55 size_t size, enum dma_data_direction direction);
56extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
57 size_t size, enum dma_data_direction direction);
58extern 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);
61extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
62 size_t size, enum dma_data_direction direction);
63extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
64 enum dma_data_direction direction);
65extern 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 */
267struct 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
47extern struct dma_mapping_ops ibmebus_dma_ops;
48extern struct bus_type ibmebus_bus_type; 47extern struct bus_type ibmebus_bus_type;
49 48
50struct ibmebus_dev { 49struct 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);
79extern struct iommu_table *iommu_init_table(struct iommu_table * tbl, 79extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
80 int nid); 80 int nid);
81 81
82extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, 82extern 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);
85extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, 85extern 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
88extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 88extern 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);
91extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, 91extern 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);
93extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 93extern 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);
96extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, 96extern 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
99extern void iommu_init_early_pSeries(void); 99extern void iommu_init_early_pSeries(void);
100extern void iommu_init_early_iSeries(void); 100extern 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
24struct pci_dev;
24struct device_node; 25struct device_node;
25struct iommu_table; 26struct iommu_table;
26 27
27/* Creates table for an individual device node */ 28/* Creates table for an individual device node */
28extern void iommu_devnode_init_iSeries(struct device_node *dn); 29extern 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 */
31extern void iommu_table_getparms_iSeries(unsigned long busno, 33extern 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 */
15struct of_device 15struct 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
73extern struct dma_mapping_ops pci_dma_ops; 73extern 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 */
78static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) 78static 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);
210extern void pcibios_fixup_device_resources(struct pci_dev *dev, 210extern void pcibios_fixup_device_resources(struct pci_dev *dev,
211 struct pci_bus *bus); 211 struct pci_bus *bus);
212 212
213extern void pcibios_setup_new_device(struct pci_dev *dev);
214
213extern void pcibios_claim_one_bus(struct pci_bus *b); 215extern void pcibios_claim_one_bus(struct pci_bus *b);
214 216
215extern struct pci_controller *init_phb_dynamic(struct device_node *dn); 217extern 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 */
47struct vio_dev { 47struct 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;