aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-11-26 11:21:24 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-01-03 08:10:09 -0500
commitfc2100eb4d0960b56c2c705a97941c08fb1c0fd4 (patch)
tree363dab8ecff94ec0306d165d8711df414486f7f8 /drivers/base
parent4a77a6cf6d9bf9f5c74b27f62bd2bfe6dcc88392 (diff)
add frontend implementation for the IOMMU API
This API can be used by KVM for accessing different types of IOMMUs to do device passthrough to guests. Beside that this API can also be used by device drivers to map non-linear host memory into dma-linear addresses to prevent sgather-gather DMA. UIO may be another user for this API. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/iommu.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
new file mode 100644
index 000000000000..5e039d4f877c
--- /dev/null
+++ b/drivers/base/iommu.c
@@ -0,0 +1,100 @@
1/*
2 * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
3 * Author: Joerg Roedel <joerg.roedel@amd.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <linux/bug.h>
20#include <linux/types.h>
21#include <linux/errno.h>
22#include <linux/iommu.h>
23
24static struct iommu_ops *iommu_ops;
25
26void register_iommu(struct iommu_ops *ops)
27{
28 if (iommu_ops)
29 BUG();
30
31 iommu_ops = ops;
32}
33
34bool iommu_found()
35{
36 return iommu_ops != NULL;
37}
38EXPORT_SYMBOL_GPL(iommu_found);
39
40struct iommu_domain *iommu_domain_alloc(void)
41{
42 struct iommu_domain *domain;
43 int ret;
44
45 domain = kmalloc(sizeof(*domain), GFP_KERNEL);
46 if (!domain)
47 return NULL;
48
49 ret = iommu_ops->domain_init(domain);
50 if (ret)
51 goto out_free;
52
53 return domain;
54
55out_free:
56 kfree(domain);
57
58 return NULL;
59}
60EXPORT_SYMBOL_GPL(iommu_domain_alloc);
61
62void iommu_domain_free(struct iommu_domain *domain)
63{
64 iommu_ops->domain_destroy(domain);
65 kfree(domain);
66}
67EXPORT_SYMBOL_GPL(iommu_domain_free);
68
69int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
70{
71 return iommu_ops->attach_dev(domain, dev);
72}
73EXPORT_SYMBOL_GPL(iommu_attach_device);
74
75void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
76{
77 iommu_ops->detach_dev(domain, dev);
78}
79EXPORT_SYMBOL_GPL(iommu_detach_device);
80
81int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
82 phys_addr_t paddr, size_t size, int prot)
83{
84 return iommu_ops->map(domain, iova, paddr, size, prot);
85}
86EXPORT_SYMBOL_GPL(iommu_map_range);
87
88void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
89 size_t size)
90{
91 iommu_ops->unmap(domain, iova, size);
92}
93EXPORT_SYMBOL_GPL(iommu_unmap_range);
94
95phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
96 unsigned long iova)
97{
98 return iommu_ops->iova_to_phys(domain, iova);
99}
100EXPORT_SYMBOL_GPL(iommu_iova_to_phys);