msm: iommu: Restructure iommu domains
Each domain iova space is now partitioned via an array
of memory pools. This makes it easier to understand the
partitioning of the iova space for a given domain.
Change-Id: If83d03a4a97eb5db529cd80f1f956a3602cc4ce4
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index 41d8072..11fe26c 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -208,58 +208,18 @@
return 0;
}
-static unsigned long allocate_iova_address(unsigned long size,
- int subsys_id,
- unsigned long align)
-{
- struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
- unsigned long iova;
-
- iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
- if (iova)
- pool->free -= size;
-
- return iova;
-}
-
-static void free_iova_address(unsigned long iova,
- unsigned long size,
- int subsys_id)
-{
- struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
-
- pool->free += size;
- gen_pool_free(pool->gpool, iova, size);
-}
-
-static int subsys_validate(int subsys_id)
-{
- struct mem_pool *pool;
- struct iommu_domain *subsys_domain;
-
- if (!msm_subsystem_check_id(subsys_id)) {
- WARN(1, "subsystem id is not valid. Caller should check this.");
- return 0;
- }
-
- pool = msm_subsystem_get_pool(subsys_id);
- subsys_domain = msm_subsystem_get_domain(subsys_id);
-
- return subsys_domain && pool && pool->gpool;
-}
-
phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
{
struct iommu_domain *subsys_domain;
- if (!subsys_validate(subsys_id))
+ if (!msm_use_iommu())
/*
- * If the subsystem is not valid, assume a phys = iova
- * mapping. Just return the iova in this case.
+ * If there is no iommu, Just return the iova in this case.
*/
return iova;
- subsys_domain = msm_subsystem_get_domain(subsys_id);
+ subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
+ (subsys_id));
return iommu_iova_to_phys(subsys_domain, iova);
}
@@ -355,15 +315,29 @@
min_align = flags & ~(SZ_4K - 1);
for (i = 0; i < nsubsys; i++) {
- if (!subsys_validate(subsys_ids[i])) {
+ unsigned int domain_no, partition_no;
+
+ if (!msm_use_iommu()) {
buf->iova[i] = phys;
continue;
}
- d = msm_subsystem_get_domain(subsys_ids[i]);
+ d = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(subsys_ids[i]));
- iova_start = allocate_iova_address(length,
- subsys_ids[i],
+ if (!d) {
+ pr_err("%s: could not get domain for subsystem"
+ " %d\n", __func__, subsys_ids[i]);
+ continue;
+ }
+
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
+
+ iova_start = msm_allocate_iova_address(domain_no,
+ partition_no,
+ length,
max(min_align, SZ_4K));
if (!iova_start) {
@@ -410,19 +384,26 @@
iommu_unmap(d, temp_va, get_order(SZ_4K));
outdomain:
if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
+ /* Unmap the rest of the current domain, i */
for (j -= SZ_4K, temp_va -= SZ_4K;
j > 0; temp_va -= SZ_4K, j -= SZ_4K)
iommu_unmap(d, temp_va, get_order(SZ_4K));
+ /* Unmap all the other domains */
for (i--; i >= 0; i--) {
- if (!subsys_validate(subsys_ids[i]))
+ unsigned int domain_no, partition_no;
+ if (!msm_use_iommu())
continue;
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
temp_va = buf->iova[i];
for (j = length; j > 0; j -= SZ_4K,
temp_va += SZ_4K)
iommu_unmap(d, temp_va, get_order(SZ_4K));
- free_iova_address(buf->iova[i], length, subsys_ids[i]);
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, length);
}
kfree(buf->iova);
@@ -464,25 +445,32 @@
}
if (buf->iova) {
- for (i = 0; i < node->nsubsys; i++) {
- struct iommu_domain *subsys_domain;
+ if (msm_use_iommu())
+ for (i = 0; i < node->nsubsys; i++) {
+ struct iommu_domain *subsys_domain;
+ unsigned int domain_no, partition_no;
- if (!subsys_validate(node->subsystems[i]))
- continue;
+ subsys_domain = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(
+ node->subsystems[i]));
- subsys_domain = msm_subsystem_get_domain(
+ domain_no = msm_subsystem_get_domain_no(
node->subsystems[i]);
- temp_va = buf->iova[i];
- for (j = node->length; j > 0; j -= SZ_4K,
- temp_va += SZ_4K) {
- ret = iommu_unmap(subsys_domain, temp_va,
+ partition_no = msm_subsystem_get_partition_no(
+ node->subsystems[i]);
+
+ temp_va = buf->iova[i];
+ for (j = node->length; j > 0; j -= SZ_4K,
+ temp_va += SZ_4K) {
+ ret = iommu_unmap(subsys_domain,
+ temp_va,
get_order(SZ_4K));
- WARN(ret, "iommu_unmap returned a non-zero"
- " value.\n");
+ WARN(ret, "iommu_unmap returned a "
+ " non-zero value.\n");
+ }
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, node->length);
}
- free_iova_address(buf->iova[i], node->length,
- node->subsystems[i]);
- }
kfree(buf->iova);
}