Blame view
drivers/iommu/iommu.c
4.66 KB
fc2100eb4 add frontend impl... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. * Author: Joerg Roedel <joerg.roedel@amd.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
905d66c1e iommu/core: Add b... |
18 |
#include <linux/device.h> |
409981884 iommu/core: use t... |
19 |
#include <linux/kernel.h> |
fc2100eb4 add frontend impl... |
20 21 |
#include <linux/bug.h> #include <linux/types.h> |
60db40278 drivers/base/iomm... |
22 23 |
#include <linux/module.h> #include <linux/slab.h> |
fc2100eb4 add frontend impl... |
24 25 |
#include <linux/errno.h> #include <linux/iommu.h> |
ff21776d1 Driver core: Add ... |
26 27 28 |
static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) { } |
fc2100eb4 add frontend impl... |
29 |
|
ff21776d1 Driver core: Add ... |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/** * bus_set_iommu - set iommu-callbacks for the bus * @bus: bus. * @ops: the callbacks provided by the iommu-driver * * This function is called by an iommu driver to set the iommu methods * used for a particular bus. Drivers for devices on that bus can use * the iommu-api after these ops are registered. * This special function is needed because IOMMUs are usually devices on * the bus itself, so the iommu drivers are not initialized when the bus * is set up. With this function the iommu-driver can set the iommu-ops * afterwards. */ int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops) |
fc2100eb4 add frontend impl... |
44 |
{ |
ff21776d1 Driver core: Add ... |
45 46 |
if (bus->iommu_ops != NULL) return -EBUSY; |
fc2100eb4 add frontend impl... |
47 |
|
ff21776d1 Driver core: Add ... |
48 49 50 51 |
bus->iommu_ops = ops; /* Do IOMMU specific setup for this bus-type */ iommu_bus_init(bus, ops); |
fc2100eb4 add frontend impl... |
52 |
|
ff21776d1 Driver core: Add ... |
53 |
return 0; |
fc2100eb4 add frontend impl... |
54 |
} |
ff21776d1 Driver core: Add ... |
55 |
EXPORT_SYMBOL_GPL(bus_set_iommu); |
fc2100eb4 add frontend impl... |
56 |
|
a1b60c1cd iommu/core: Conve... |
57 |
bool iommu_present(struct bus_type *bus) |
fc2100eb4 add frontend impl... |
58 |
{ |
94441c3bd iommu/core: Remov... |
59 |
return bus->iommu_ops != NULL; |
fc2100eb4 add frontend impl... |
60 |
} |
a1b60c1cd iommu/core: Conve... |
61 |
EXPORT_SYMBOL_GPL(iommu_present); |
fc2100eb4 add frontend impl... |
62 |
|
4f3f8d9db iommu/core: Add f... |
63 64 65 66 |
/** * iommu_set_fault_handler() - set a fault handler for an iommu domain * @domain: iommu domain * @handler: fault handler |
0ed6d2d27 iommu/core: let d... |
67 68 69 70 71 72 |
* * This function should be used by IOMMU users which want to be notified * whenever an IOMMU fault happens. * * The fault handler itself should return 0 on success, and an appropriate * error code otherwise. |
4f3f8d9db iommu/core: Add f... |
73 74 75 76 77 78 79 80 |
*/ void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler) { BUG_ON(!domain); domain->handler = handler; } |
30bd918c7 iommu/core: expor... |
81 |
EXPORT_SYMBOL_GPL(iommu_set_fault_handler); |
4f3f8d9db iommu/core: Add f... |
82 |
|
905d66c1e iommu/core: Add b... |
83 |
struct iommu_domain *iommu_domain_alloc(struct bus_type *bus) |
fc2100eb4 add frontend impl... |
84 85 86 |
{ struct iommu_domain *domain; int ret; |
94441c3bd iommu/core: Remov... |
87 |
if (bus == NULL || bus->iommu_ops == NULL) |
905d66c1e iommu/core: Add b... |
88 |
return NULL; |
fc2100eb4 add frontend impl... |
89 90 91 |
domain = kmalloc(sizeof(*domain), GFP_KERNEL); if (!domain) return NULL; |
94441c3bd iommu/core: Remov... |
92 |
domain->ops = bus->iommu_ops; |
905d66c1e iommu/core: Add b... |
93 |
|
94441c3bd iommu/core: Remov... |
94 |
ret = domain->ops->domain_init(domain); |
fc2100eb4 add frontend impl... |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
if (ret) goto out_free; return domain; out_free: kfree(domain); return NULL; } EXPORT_SYMBOL_GPL(iommu_domain_alloc); void iommu_domain_free(struct iommu_domain *domain) { |
e5aa7f007 iommu/core: Use b... |
109 110 |
if (likely(domain->ops->domain_destroy != NULL)) domain->ops->domain_destroy(domain); |
fc2100eb4 add frontend impl... |
111 112 113 114 115 116 |
kfree(domain); } EXPORT_SYMBOL_GPL(iommu_domain_free); int iommu_attach_device(struct iommu_domain *domain, struct device *dev) { |
e5aa7f007 iommu/core: Use b... |
117 118 119 120 |
if (unlikely(domain->ops->attach_dev == NULL)) return -ENODEV; return domain->ops->attach_dev(domain, dev); |
fc2100eb4 add frontend impl... |
121 122 123 124 125 |
} EXPORT_SYMBOL_GPL(iommu_attach_device); void iommu_detach_device(struct iommu_domain *domain, struct device *dev) { |
e5aa7f007 iommu/core: Use b... |
126 127 128 129 |
if (unlikely(domain->ops->detach_dev == NULL)) return; domain->ops->detach_dev(domain, dev); |
fc2100eb4 add frontend impl... |
130 131 |
} EXPORT_SYMBOL_GPL(iommu_detach_device); |
fc2100eb4 add frontend impl... |
132 133 134 |
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova) { |
e5aa7f007 iommu/core: Use b... |
135 136 137 138 |
if (unlikely(domain->ops->iova_to_phys == NULL)) return 0; return domain->ops->iova_to_phys(domain, iova); |
fc2100eb4 add frontend impl... |
139 140 |
} EXPORT_SYMBOL_GPL(iommu_iova_to_phys); |
dbb9fd863 iommu: Add domain... |
141 142 143 144 |
int iommu_domain_has_cap(struct iommu_domain *domain, unsigned long cap) { |
e5aa7f007 iommu/core: Use b... |
145 146 147 148 |
if (unlikely(domain->ops->domain_has_cap == NULL)) return 0; return domain->ops->domain_has_cap(domain, cap); |
dbb9fd863 iommu: Add domain... |
149 150 |
} EXPORT_SYMBOL_GPL(iommu_domain_has_cap); |
cefc53c7f iommu-api: Add io... |
151 152 153 154 |
int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, int gfp_order, int prot) { |
cefc53c7f iommu-api: Add io... |
155 |
size_t size; |
e5aa7f007 iommu/core: Use b... |
156 157 |
if (unlikely(domain->ops->map == NULL)) return -ENODEV; |
cefc53c7f iommu-api: Add io... |
158 |
|
85410340e iommu/core: Use P... |
159 |
size = PAGE_SIZE << gfp_order; |
cefc53c7f iommu-api: Add io... |
160 |
|
409981884 iommu/core: use t... |
161 |
BUG_ON(!IS_ALIGNED(iova | paddr, size)); |
cefc53c7f iommu-api: Add io... |
162 |
|
e5aa7f007 iommu/core: Use b... |
163 |
return domain->ops->map(domain, iova, paddr, gfp_order, prot); |
cefc53c7f iommu-api: Add io... |
164 165 166 167 168 |
} EXPORT_SYMBOL_GPL(iommu_map); int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) { |
cefc53c7f iommu-api: Add io... |
169 |
size_t size; |
e5aa7f007 iommu/core: Use b... |
170 171 |
if (unlikely(domain->ops->unmap == NULL)) return -ENODEV; |
85410340e iommu/core: Use P... |
172 |
size = PAGE_SIZE << gfp_order; |
cefc53c7f iommu-api: Add io... |
173 |
|
409981884 iommu/core: use t... |
174 |
BUG_ON(!IS_ALIGNED(iova, size)); |
cefc53c7f iommu-api: Add io... |
175 |
|
e5aa7f007 iommu/core: Use b... |
176 |
return domain->ops->unmap(domain, iova, gfp_order); |
cefc53c7f iommu-api: Add io... |
177 178 |
} EXPORT_SYMBOL_GPL(iommu_unmap); |