projects
/
linux-2.6-microblaze.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branches 'arm/exynos', 'arm/renesas', 'arm/rockchip', 'arm/omap', 'arm/mediatek...
[linux-2.6-microblaze.git]
/
drivers
/
iommu
/
iommu.c
diff --git
a/drivers/iommu/iommu.c
b/drivers/iommu/iommu.c
index
3f6ea16
..
3de5c0b
100644
(file)
--- a/
drivers/iommu/iommu.c
+++ b/
drivers/iommu/iommu.c
@@
-527,6
+527,8
@@
static int iommu_group_create_direct_mappings(struct iommu_group *group,
}
}
+ iommu_flush_tlb_all(domain);
+
out:
iommu_put_resv_regions(dev, &mappings);
out:
iommu_put_resv_regions(dev, &mappings);
@@
-1005,11
+1007,10
@@
struct iommu_group *iommu_group_get_for_dev(struct device *dev)
if (group)
return group;
if (group)
return group;
- group = ERR_PTR(-EINVAL);
-
- if (ops && ops->device_group)
- group = ops->device_group(dev);
+ if (!ops)
+ return ERR_PTR(-EINVAL);
+ group = ops->device_group(dev);
if (WARN_ON_ONCE(group == NULL))
return ERR_PTR(-EINVAL);
if (WARN_ON_ONCE(group == NULL))
return ERR_PTR(-EINVAL);
@@
-1283,6
+1284,10
@@
static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev)
{
int ret;
struct device *dev)
{
int ret;
+ if ((domain->ops->is_attach_deferred != NULL) &&
+ domain->ops->is_attach_deferred(domain, dev))
+ return 0;
+
if (unlikely(domain->ops->attach_dev == NULL))
return -ENODEV;
if (unlikely(domain->ops->attach_dev == NULL))
return -ENODEV;
@@
-1298,12
+1303,8
@@
int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
int ret;
group = iommu_group_get(dev);
int ret;
group = iommu_group_get(dev);
- /* FIXME: Remove this when groups a mandatory for iommu drivers */
- if (group == NULL)
- return __iommu_attach_device(domain, dev);
-
/*
/*
- *
We have a group - lock it
to make sure the device-count doesn't
+ *
Lock the group
to make sure the device-count doesn't
* change while we are attaching
*/
mutex_lock(&group->mutex);
* change while we are attaching
*/
mutex_lock(&group->mutex);
@@
-1324,6
+1325,10
@@
EXPORT_SYMBOL_GPL(iommu_attach_device);
static void __iommu_detach_device(struct iommu_domain *domain,
struct device *dev)
{
static void __iommu_detach_device(struct iommu_domain *domain,
struct device *dev)
{
+ if ((domain->ops->is_attach_deferred != NULL) &&
+ domain->ops->is_attach_deferred(domain, dev))
+ return;
+
if (unlikely(domain->ops->detach_dev == NULL))
return;
if (unlikely(domain->ops->detach_dev == NULL))
return;
@@
-1336,9
+1341,6
@@
void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
struct iommu_group *group;
group = iommu_group_get(dev);
struct iommu_group *group;
group = iommu_group_get(dev);
- /* FIXME: Remove this when groups a mandatory for iommu drivers */
- if (group == NULL)
- return __iommu_detach_device(domain, dev);
mutex_lock(&group->mutex);
if (iommu_group_device_count(group) != 1) {
mutex_lock(&group->mutex);
if (iommu_group_device_count(group) != 1) {
@@
-1360,8
+1362,7
@@
struct iommu_domain *iommu_get_domain_for_dev(struct device *dev)
struct iommu_group *group;
group = iommu_group_get(dev);
struct iommu_group *group;
group = iommu_group_get(dev);
- /* FIXME: Remove this when groups a mandatory for iommu drivers */
- if (group == NULL)
+ if (!group)
return NULL;
domain = group->domain;
return NULL;
domain = group->domain;
@@
-1556,13
+1557,16
@@
int iommu_map(struct iommu_domain *domain, unsigned long iova,
}
EXPORT_SYMBOL_GPL(iommu_map);
}
EXPORT_SYMBOL_GPL(iommu_map);
-size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
+static size_t __iommu_unmap(struct iommu_domain *domain,
+ unsigned long iova, size_t size,
+ bool sync)
{
{
+ const struct iommu_ops *ops = domain->ops;
size_t unmapped_page, unmapped = 0;
size_t unmapped_page, unmapped = 0;
- unsigned int min_pagesz;
unsigned long orig_iova = iova;
unsigned long orig_iova = iova;
+ unsigned int min_pagesz;
- if (unlikely(
domain->
ops->unmap == NULL ||
+ if (unlikely(ops->unmap == NULL ||
domain->pgsize_bitmap == 0UL))
return -ENODEV;
domain->pgsize_bitmap == 0UL))
return -ENODEV;
@@
-1592,10
+1596,13
@@
size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
while (unmapped < size) {
size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
while (unmapped < size) {
size_t pgsize = iommu_pgsize(domain, iova, size - unmapped);
- unmapped_page =
domain->
ops->unmap(domain, iova, pgsize);
+ unmapped_page = ops->unmap(domain, iova, pgsize);
if (!unmapped_page)
break;
if (!unmapped_page)
break;
+ if (sync && ops->iotlb_range_add)
+ ops->iotlb_range_add(domain, iova, pgsize);
+
pr_debug("unmapped: iova 0x%lx size 0x%zx\n",
iova, unmapped_page);
pr_debug("unmapped: iova 0x%lx size 0x%zx\n",
iova, unmapped_page);
@@
-1603,11
+1610,27
@@
size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
unmapped += unmapped_page;
}
unmapped += unmapped_page;
}
+ if (sync && ops->iotlb_sync)
+ ops->iotlb_sync(domain);
+
trace_unmap(orig_iova, size, unmapped);
return unmapped;
}
trace_unmap(orig_iova, size, unmapped);
return unmapped;
}
+
+size_t iommu_unmap(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
+{
+ return __iommu_unmap(domain, iova, size, true);
+}
EXPORT_SYMBOL_GPL(iommu_unmap);
EXPORT_SYMBOL_GPL(iommu_unmap);
+size_t iommu_unmap_fast(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
+{
+ return __iommu_unmap(domain, iova, size, false);
+}
+EXPORT_SYMBOL_GPL(iommu_unmap_fast);
+
size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
struct scatterlist *sg, unsigned int nents, int prot)
{
size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
struct scatterlist *sg, unsigned int nents, int prot)
{