aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_iommu.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:25:02 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:38:40 -0500
commit12d04eef927bf61328af2c7cbe756c96f98ac3bf (patch)
tree18865369100e9059c7e883dec93ea67f7b52a287 /arch/powerpc/kernel/pci_iommu.c
parent7c719871ff4d5f15b71f0138d08b758281b58631 (diff)
[POWERPC] Refactor 64 bits DMA operations
This patch completely refactors DMA operations for 64 bits powerpc. 32 bits is untouched for now. We use the new dev_archdata structure to add the dma operations pointer and associated data to struct device. While at it, we also add the OF node pointer and numa node. In the future, we might want to look into merging that with pci_dn as well. The old vio, pci-iommu and pci-direct DMA ops are gone. They are now replaced by a set of generic iommu and direct DMA ops (non PCI specific) that can be used by bus types. The toplevel implementation is now inline. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_iommu.c')
-rw-r--r--arch/powerpc/kernel/pci_iommu.c164
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
47static inline struct iommu_table *device_to_table(struct device *hwdev)
48{
49 struct pci_dev *pdev;
50
51 if (!hwdev) {
52 pdev = ppc64_isabridge_dev;
53 if (!pdev)
54 return NULL;
55 } else
56 pdev = to_pci_dev(hwdev);
57
58 return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
59}
60
61
62static inline unsigned long device_to_mask(struct device *hwdev)
63{
64 struct pci_dev *pdev;
65
66 if (!hwdev) {
67 pdev = ppc64_isabridge_dev;
68 if (!pdev) /* This is the best guess we can do */
69 return 0xfffffffful;
70 } else
71 pdev = to_pci_dev(hwdev);
72
73 if (pdev->dma_mask)
74 return pdev->dma_mask;
75
76 /* Assume devices without mask can take 32 bit addresses */
77 return 0xfffffffful;
78}
79
80
81/* Allocates a contiguous real buffer and creates mappings over it.
82 * Returns the virtual address of the buffer and sets dma_handle
83 * to the dma address (mapping) of the first page.
84 */
85static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
86 dma_addr_t *dma_handle, gfp_t flag)
87{
88 return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
89 device_to_mask(hwdev), flag,
90 pcibus_to_node(to_pci_dev(hwdev)->bus));
91}
92
93static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
94 void *vaddr, dma_addr_t dma_handle)
95{
96 iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
97}
98
99/* Creates TCEs for a user provided buffer. The user buffer must be
100 * contiguous real kernel storage (not vmalloc). The address of the buffer
101 * passed here is the kernel (virtual) address of the buffer. The buffer
102 * need not be page aligned, the dma_addr_t returned will point to the same
103 * byte within the page as vaddr.
104 */
105static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
106 size_t size, enum dma_data_direction direction)
107{
108 return iommu_map_single(device_to_table(hwdev), vaddr, size,
109 device_to_mask(hwdev), direction);
110}
111
112
113static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
114 size_t size, enum dma_data_direction direction)
115{
116 iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
117}
118
119
120static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
121 int nelems, enum dma_data_direction direction)
122{
123 return iommu_map_sg(pdev, device_to_table(pdev), sglist,
124 nelems, device_to_mask(pdev), direction);
125}
126
127static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
128 int nelems, enum dma_data_direction direction)
129{
130 iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
131}
132
133/* We support DMA to/from any memory page via the iommu */
134static int pci_iommu_dma_supported(struct device *dev, u64 mask)
135{
136 struct iommu_table *tbl = device_to_table(dev);
137
138 if (!tbl || tbl->it_offset > mask) {
139 printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
140 if (tbl)
141 printk(KERN_INFO "mask: 0x%08lx, table offset: 0x%08lx\n",
142 mask, tbl->it_offset);
143 else
144 printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
145 mask);
146 return 0;
147 } else
148 return 1;
149}
150
151struct dma_mapping_ops pci_iommu_ops = {
152 .alloc_coherent = pci_iommu_alloc_coherent,
153 .free_coherent = pci_iommu_free_coherent,
154 .map_single = pci_iommu_map_single,
155 .unmap_single = pci_iommu_unmap_single,
156 .map_sg = pci_iommu_map_sg,
157 .unmap_sg = pci_iommu_unmap_sg,
158 .dma_supported = pci_iommu_dma_supported,
159};
160
161void pci_iommu_init(void)
162{
163 pci_dma_ops = pci_iommu_ops;
164}