diff options
Diffstat (limited to 'arch/powerpc/kernel/pci_iommu.c')
-rw-r--r-- | arch/powerpc/kernel/pci_iommu.c | 164 |
1 files changed, 0 insertions, 164 deletions
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 | } | ||