summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/iommu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 20:09:17 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 20:09:17 +0100
commitf6c0ffa8f0b0781f4954cb06f0a81d6c10c1b434 (patch)
treef99190661706d18f129497a4ef2d37822c9c34db /drivers/iommu/iommu.c
parentMerge branch 'for-v3.9' of git://git.linaro.org/people/mszyprowski/linux-dma-... (diff)
parentMerge branches 'core', 'arm/omap', 'iommu/fixes', 'arm/tegra', 'arm/shmobile'... (diff)
downloadlinux-f6c0ffa8f0b0781f4954cb06f0a81d6c10c1b434.tar.xz
linux-f6c0ffa8f0b0781f4954cb06f0a81d6c10c1b434.zip
Merge tag 'iommu-updates-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU Updates from Joerg Roedel: "Besides some fixes and cleanups in the code there are three more important changes to point out this time: * New IOMMU driver for the ARM SHMOBILE platform * An IOMMU-API extension for non-paging IOMMUs (required for upcoming PAMU driver) * Rework of the way the Tegra IOMMU driver accesses its registetrs - register windows are easier to extend now. There are also a few changes to non-iommu code, but that is acked by the respective maintainers." * tag 'iommu-updates-v3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (23 commits) iommu/tegra: assume CONFIG_OF in SMMU driver iommu/tegra: assume CONFIG_OF in gart driver iommu/amd: Remove redundant NULL check before dma_ops_domain_free(). iommu/amd: Initialize device table after dma_ops iommu/vt-d: Zero out allocated memory in dmar_enable_qi iommu/tegra: smmu: Fix incorrect mask for regbase iommu/exynos: Make exynos_sysmmu_disable static ARM: mach-shmobile: r8a7740: Add IPMMU device ARM: mach-shmobile: sh73a0: Add IPMMU device ARM: mach-shmobile: sh7372: Add IPMMU device iommu/shmobile: Add iommu driver for Renesas IPMMU modules iommu: Add DOMAIN_ATTR_WINDOWS domain attribute iommu: Add domain window handling functions iommu: Implement DOMAIN_ATTR_PAGING attribute iommu: Check for valid pgsize_bitmap in iommu_map/unmap iommu: Make sure DOMAIN_ATTR_MAX is really the maximum iommu/tegra: smmu: Change SMMU's dependency on ARCH_TEGRA iommu/tegra: smmu: Use helper function to check for valid register offset iommu/tegra: smmu: Support variable MMIO ranges/blocks iommu/tegra: Add missing spinlock initialization ...
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r--drivers/iommu/iommu.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index ddbdacad7768..b972d430d92b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -734,7 +734,8 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
size_t orig_size = size;
int ret = 0;
- if (unlikely(domain->ops->map == NULL))
+ if (unlikely(domain->ops->unmap == NULL ||
+ domain->ops->pgsize_bitmap == 0UL))
return -ENODEV;
/* find out the minimum page size supported */
@@ -808,7 +809,8 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
size_t unmapped_page, unmapped = 0;
unsigned int min_pagesz;
- if (unlikely(domain->ops->unmap == NULL))
+ if (unlikely(domain->ops->unmap == NULL ||
+ domain->ops->pgsize_bitmap == 0UL))
return -ENODEV;
/* find out the minimum page size supported */
@@ -850,6 +852,26 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
}
EXPORT_SYMBOL_GPL(iommu_unmap);
+
+int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
+ phys_addr_t paddr, u64 size)
+{
+ if (unlikely(domain->ops->domain_window_enable == NULL))
+ return -ENODEV;
+
+ return domain->ops->domain_window_enable(domain, wnd_nr, paddr, size);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_window_enable);
+
+void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
+{
+ if (unlikely(domain->ops->domain_window_disable == NULL))
+ return;
+
+ return domain->ops->domain_window_disable(domain, wnd_nr);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_window_disable);
+
static int __init iommu_init(void)
{
iommu_group_kset = kset_create_and_add("iommu_groups",
@@ -861,13 +883,15 @@ static int __init iommu_init(void)
return 0;
}
-subsys_initcall(iommu_init);
+arch_initcall(iommu_init);
int iommu_domain_get_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
{
struct iommu_domain_geometry *geometry;
+ bool *paging;
int ret = 0;
+ u32 *count;
switch (attr) {
case DOMAIN_ATTR_GEOMETRY:
@@ -875,6 +899,19 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
*geometry = domain->geometry;
break;
+ case DOMAIN_ATTR_PAGING:
+ paging = data;
+ *paging = (domain->ops->pgsize_bitmap != 0UL);
+ break;
+ case DOMAIN_ATTR_WINDOWS:
+ count = data;
+
+ if (domain->ops->domain_get_windows != NULL)
+ *count = domain->ops->domain_get_windows(domain);
+ else
+ ret = -ENODEV;
+
+ break;
default:
if (!domain->ops->domain_get_attr)
return -EINVAL;
@@ -889,9 +926,26 @@ EXPORT_SYMBOL_GPL(iommu_domain_get_attr);
int iommu_domain_set_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
{
- if (!domain->ops->domain_set_attr)
- return -EINVAL;
+ int ret = 0;
+ u32 *count;
- return domain->ops->domain_set_attr(domain, attr, data);
+ switch (attr) {
+ case DOMAIN_ATTR_WINDOWS:
+ count = data;
+
+ if (domain->ops->domain_set_windows != NULL)
+ ret = domain->ops->domain_set_windows(domain, *count);
+ else
+ ret = -ENODEV;
+
+ break;
+ default:
+ if (domain->ops->domain_set_attr == NULL)
+ return -EINVAL;
+
+ ret = domain->ops->domain_set_attr(domain, attr, data);
+ }
+
+ return ret;
}
EXPORT_SYMBOL_GPL(iommu_domain_set_attr);