aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r--drivers/iommu/iommu.c113
1 files changed, 58 insertions, 55 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index edbdf5d6962c..3ed4db334341 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -22,7 +22,8 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/bug.h> 23#include <linux/bug.h>
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/module.h> 25#include <linux/init.h>
26#include <linux/export.h>
26#include <linux/slab.h> 27#include <linux/slab.h>
27#include <linux/errno.h> 28#include <linux/errno.h>
28#include <linux/iommu.h> 29#include <linux/iommu.h>
@@ -110,6 +111,27 @@ void iommu_device_unregister(struct iommu_device *iommu)
110 spin_unlock(&iommu_device_lock); 111 spin_unlock(&iommu_device_lock);
111} 112}
112 113
114int iommu_probe_device(struct device *dev)
115{
116 const struct iommu_ops *ops = dev->bus->iommu_ops;
117 int ret = -EINVAL;
118
119 WARN_ON(dev->iommu_group);
120
121 if (ops)
122 ret = ops->add_device(dev);
123
124 return ret;
125}
126
127void iommu_release_device(struct device *dev)
128{
129 const struct iommu_ops *ops = dev->bus->iommu_ops;
130
131 if (dev->iommu_group)
132 ops->remove_device(dev);
133}
134
113static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, 135static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
114 unsigned type); 136 unsigned type);
115static int __iommu_attach_device(struct iommu_domain *domain, 137static int __iommu_attach_device(struct iommu_domain *domain,
@@ -1117,16 +1139,7 @@ struct iommu_domain *iommu_group_default_domain(struct iommu_group *group)
1117 1139
1118static int add_iommu_group(struct device *dev, void *data) 1140static int add_iommu_group(struct device *dev, void *data)
1119{ 1141{
1120 struct iommu_callback_data *cb = data; 1142 int ret = iommu_probe_device(dev);
1121 const struct iommu_ops *ops = cb->ops;
1122 int ret;
1123
1124 if (!ops->add_device)
1125 return 0;
1126
1127 WARN_ON(dev->iommu_group);
1128
1129 ret = ops->add_device(dev);
1130 1143
1131 /* 1144 /*
1132 * We ignore -ENODEV errors for now, as they just mean that the 1145 * We ignore -ENODEV errors for now, as they just mean that the
@@ -1141,11 +1154,7 @@ static int add_iommu_group(struct device *dev, void *data)
1141 1154
1142static int remove_iommu_group(struct device *dev, void *data) 1155static int remove_iommu_group(struct device *dev, void *data)
1143{ 1156{
1144 struct iommu_callback_data *cb = data; 1157 iommu_release_device(dev);
1145 const struct iommu_ops *ops = cb->ops;
1146
1147 if (ops->remove_device && dev->iommu_group)
1148 ops->remove_device(dev);
1149 1158
1150 return 0; 1159 return 0;
1151} 1160}
@@ -1153,27 +1162,22 @@ static int remove_iommu_group(struct device *dev, void *data)
1153static int iommu_bus_notifier(struct notifier_block *nb, 1162static int iommu_bus_notifier(struct notifier_block *nb,
1154 unsigned long action, void *data) 1163 unsigned long action, void *data)
1155{ 1164{
1165 unsigned long group_action = 0;
1156 struct device *dev = data; 1166 struct device *dev = data;
1157 const struct iommu_ops *ops = dev->bus->iommu_ops;
1158 struct iommu_group *group; 1167 struct iommu_group *group;
1159 unsigned long group_action = 0;
1160 1168
1161 /* 1169 /*
1162 * ADD/DEL call into iommu driver ops if provided, which may 1170 * ADD/DEL call into iommu driver ops if provided, which may
1163 * result in ADD/DEL notifiers to group->notifier 1171 * result in ADD/DEL notifiers to group->notifier
1164 */ 1172 */
1165 if (action == BUS_NOTIFY_ADD_DEVICE) { 1173 if (action == BUS_NOTIFY_ADD_DEVICE) {
1166 if (ops->add_device) { 1174 int ret;
1167 int ret;
1168 1175
1169 ret = ops->add_device(dev); 1176 ret = iommu_probe_device(dev);
1170 return (ret) ? NOTIFY_DONE : NOTIFY_OK; 1177 return (ret) ? NOTIFY_DONE : NOTIFY_OK;
1171 }
1172 } else if (action == BUS_NOTIFY_REMOVED_DEVICE) { 1178 } else if (action == BUS_NOTIFY_REMOVED_DEVICE) {
1173 if (ops->remove_device && dev->iommu_group) { 1179 iommu_release_device(dev);
1174 ops->remove_device(dev); 1180 return NOTIFY_OK;
1175 return 0;
1176 }
1177 } 1181 }
1178 1182
1179 /* 1183 /*
@@ -1712,33 +1716,32 @@ EXPORT_SYMBOL_GPL(iommu_unmap_fast);
1712size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, 1716size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
1713 struct scatterlist *sg, unsigned int nents, int prot) 1717 struct scatterlist *sg, unsigned int nents, int prot)
1714{ 1718{
1715 struct scatterlist *s; 1719 size_t len = 0, mapped = 0;
1716 size_t mapped = 0; 1720 phys_addr_t start;
1717 unsigned int i, min_pagesz; 1721 unsigned int i = 0;
1718 int ret; 1722 int ret;
1719 1723
1720 if (unlikely(domain->pgsize_bitmap == 0UL)) 1724 while (i <= nents) {
1721 return 0; 1725 phys_addr_t s_phys = sg_phys(sg);
1722 1726
1723 min_pagesz = 1 << __ffs(domain->pgsize_bitmap); 1727 if (len && s_phys != start + len) {
1724 1728 ret = iommu_map(domain, iova + mapped, start, len, prot);
1725 for_each_sg(sg, s, nents, i) { 1729 if (ret)
1726 phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset; 1730 goto out_err;
1727 1731
1728 /* 1732 mapped += len;
1729 * We are mapping on IOMMU page boundaries, so offset within 1733 len = 0;
1730 * the page must be 0. However, the IOMMU may support pages 1734 }
1731 * smaller than PAGE_SIZE, so s->offset may still represent
1732 * an offset of that boundary within the CPU page.
1733 */
1734 if (!IS_ALIGNED(s->offset, min_pagesz))
1735 goto out_err;
1736 1735
1737 ret = iommu_map(domain, iova + mapped, phys, s->length, prot); 1736 if (len) {
1738 if (ret) 1737 len += sg->length;
1739 goto out_err; 1738 } else {
1739 len = sg->length;
1740 start = s_phys;
1741 }
1740 1742
1741 mapped += s->length; 1743 if (++i < nents)
1744 sg = sg_next(sg);
1742 } 1745 }
1743 1746
1744 return mapped; 1747 return mapped;
@@ -1976,7 +1979,7 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
1976int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, 1979int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
1977 const struct iommu_ops *ops) 1980 const struct iommu_ops *ops)
1978{ 1981{
1979 struct iommu_fwspec *fwspec = dev->iommu_fwspec; 1982 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
1980 1983
1981 if (fwspec) 1984 if (fwspec)
1982 return ops == fwspec->ops ? 0 : -EINVAL; 1985 return ops == fwspec->ops ? 0 : -EINVAL;
@@ -1988,26 +1991,26 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
1988 of_node_get(to_of_node(iommu_fwnode)); 1991 of_node_get(to_of_node(iommu_fwnode));
1989 fwspec->iommu_fwnode = iommu_fwnode; 1992 fwspec->iommu_fwnode = iommu_fwnode;
1990 fwspec->ops = ops; 1993 fwspec->ops = ops;
1991 dev->iommu_fwspec = fwspec; 1994 dev_iommu_fwspec_set(dev, fwspec);
1992 return 0; 1995 return 0;
1993} 1996}
1994EXPORT_SYMBOL_GPL(iommu_fwspec_init); 1997EXPORT_SYMBOL_GPL(iommu_fwspec_init);
1995 1998
1996void iommu_fwspec_free(struct device *dev) 1999void iommu_fwspec_free(struct device *dev)
1997{ 2000{
1998 struct iommu_fwspec *fwspec = dev->iommu_fwspec; 2001 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
1999 2002
2000 if (fwspec) { 2003 if (fwspec) {
2001 fwnode_handle_put(fwspec->iommu_fwnode); 2004 fwnode_handle_put(fwspec->iommu_fwnode);
2002 kfree(fwspec); 2005 kfree(fwspec);
2003 dev->iommu_fwspec = NULL; 2006 dev_iommu_fwspec_set(dev, NULL);
2004 } 2007 }
2005} 2008}
2006EXPORT_SYMBOL_GPL(iommu_fwspec_free); 2009EXPORT_SYMBOL_GPL(iommu_fwspec_free);
2007 2010
2008int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids) 2011int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
2009{ 2012{
2010 struct iommu_fwspec *fwspec = dev->iommu_fwspec; 2013 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
2011 size_t size; 2014 size_t size;
2012 int i; 2015 int i;
2013 2016
@@ -2016,11 +2019,11 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
2016 2019
2017 size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]); 2020 size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]);
2018 if (size > sizeof(*fwspec)) { 2021 if (size > sizeof(*fwspec)) {
2019 fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL); 2022 fwspec = krealloc(fwspec, size, GFP_KERNEL);
2020 if (!fwspec) 2023 if (!fwspec)
2021 return -ENOMEM; 2024 return -ENOMEM;
2022 2025
2023 dev->iommu_fwspec = fwspec; 2026 dev_iommu_fwspec_set(dev, fwspec);
2024 } 2027 }
2025 2028
2026 for (i = 0; i < num_ids; i++) 2029 for (i = 0; i < num_ids; i++)