iommu: msm: Only program registers once
Certain operations need to be performed only once per
IOMMU. Ensure that this is the case for both secure and non-secure
IOMMUs.
Change-Id: If16220fc5807a55daadd1c5e13a1117148445e0c
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 923e4da..c5c4988 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -97,6 +97,7 @@
* @clk_reg_virt: Optional clock register virtual address.
* @halt_enabled: Set to 1 if IOMMU halt is supported in the IOMMU, 0 otherwise.
* @asid: List of ASID and their usage count (index is ASID value).
+ * @ctx_attach_count: Count of how many context are attached.
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -119,6 +120,7 @@
void __iomem *clk_reg_virt;
int halt_enabled;
int *asid;
+ unsigned int ctx_attach_count;
};
void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 7110303..24d2854 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -506,27 +506,6 @@
mutex_unlock(&msm_iommu_lock);
}
-static int msm_iommu_ctx_attached(struct device *dev)
-{
- struct platform_device *pdev;
- struct device_node *child;
- struct msm_iommu_ctx_drvdata *ctx;
-
- for_each_child_of_node(dev->of_node, child) {
- pdev = of_find_device_by_node(child);
-
- ctx = dev_get_drvdata(&pdev->dev);
- if (ctx->attached_domain) {
- of_dev_put(pdev);
- of_node_put(child);
- return 1;
- }
- of_dev_put(pdev);
- }
-
- return 0;
-}
-
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
struct msm_priv *priv;
@@ -574,8 +553,8 @@
goto fail;
}
-
- if (!msm_iommu_ctx_attached(dev->parent)) {
+ /* We can only do this once */
+ if (!iommu_drvdata->ctx_attach_count) {
if (!is_secure) {
iommu_halt(iommu_drvdata);
__program_iommu(iommu_drvdata->base);
@@ -603,6 +582,7 @@
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
ctx_drvdata->attached_domain = domain;
+ ++iommu_drvdata->ctx_attach_count;
mutex_unlock(&msm_iommu_lock);
@@ -660,7 +640,8 @@
list_del_init(&ctx_drvdata->attached_elm);
ctx_drvdata->attached_domain = NULL;
-
+ BUG_ON(iommu_drvdata->ctx_attach_count == 0);
+ --iommu_drvdata->ctx_attach_count;
fail:
mutex_unlock(&msm_iommu_lock);
}
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 4e55bd6..29cf0c1 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -359,26 +359,30 @@
if (ret)
goto fail;
- ret = __enable_clocks(iommu_drvdata);
- if (ret) {
- regulator_disable(iommu_drvdata->gdsc);
- goto fail;
- }
+ /* We can only do this once */
+ if (!iommu_drvdata->ctx_attach_count) {
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret) {
+ regulator_disable(iommu_drvdata->gdsc);
+ goto fail;
+ }
- ret = msm_iommu_sec_program_iommu(iommu_drvdata->sec_id);
+ ret = msm_iommu_sec_program_iommu(iommu_drvdata->sec_id);
- /* bfb settings are always programmed by HLOS */
- program_iommu_bfb_settings(iommu_drvdata->base,
- iommu_drvdata->bfb_settings);
+ /* bfb settings are always programmed by HLOS */
+ program_iommu_bfb_settings(iommu_drvdata->base,
+ iommu_drvdata->bfb_settings);
- __disable_clocks(iommu_drvdata);
- if (ret) {
- regulator_disable(iommu_drvdata->gdsc);
- goto fail;
+ __disable_clocks(iommu_drvdata);
+ if (ret) {
+ regulator_disable(iommu_drvdata->gdsc);
+ goto fail;
+ }
}
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
ctx_drvdata->attached_domain = domain;
+ ++iommu_drvdata->ctx_attach_count;
mutex_unlock(&msm_iommu_lock);
@@ -410,7 +414,8 @@
ctx_drvdata->attached_domain = NULL;
regulator_disable(iommu_drvdata->gdsc);
-
+ BUG_ON(iommu_drvdata->ctx_attach_count == 0);
+ --iommu_drvdata->ctx_attach_count;
fail:
mutex_unlock(&msm_iommu_lock);
}