summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2017-04-07 15:01:42 -0600
committerJordan Crouse <jcrouse@codeaurora.org>2017-04-26 12:08:08 -0600
commitf0eb0ed585c15c7a011d7d6b3f1d0cd58751f7dd (patch)
tree0084c5fb985bedb94bed89db7d76b3cc59b4fb8e /drivers/gpu
parent4e061d8b6002fbb9c124a89f4952cebda0f0450d (diff)
drm/msm: Add enable/disable hooks for mmu
5XX targets that are using per-process pagetables will need to keep the IOMMU clocks on the entire time because we don't know exactly when the GPU might touch it. That said there are occassional depencency issues if the clocks are enabled out of order. To be certain we should enable the MMU clocks last and disable them first. Add enable/disable hooks to the MMU struct to do this cleanly from the GPU pm_resume / pm_suspend paths. Change-Id: Ic0dedbad8e2298e55c90b29eed657baa0933ddcf Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c6
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c75
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h14
3 files changed, 51 insertions, 44 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index cbc37dcce1d0..2f01db8b08c3 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -183,6 +183,9 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
if (ret)
return ret;
+ if (gpu->aspace && gpu->aspace->mmu)
+ msm_mmu_enable(gpu->aspace->mmu);
+
return 0;
}
@@ -203,6 +206,9 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
if (WARN_ON(gpu->active_cnt < 0))
return -EINVAL;
+ if (gpu->aspace && gpu->aspace->mmu)
+ msm_mmu_disable(gpu->aspace->mmu);
+
ret = disable_axi(gpu);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 38b5cd6d45df..f5d89f76dda8 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -27,49 +27,17 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
return 0;
}
-static void enable_iommu_clocks(struct msm_iommu *iommu)
-{
- int i;
-
- for (i = 0; i < iommu->nr_clocks; i++) {
- if (iommu->clocks[i])
- clk_prepare_enable(iommu->clocks[i]);
- }
-}
-
-static void disable_iommu_clocks(struct msm_iommu *iommu)
-{
- int i;
-
- for (i = 0; i < iommu->nr_clocks; i++) {
- if (iommu->clocks[i])
- clk_disable_unprepare(iommu->clocks[i]);
- }
-}
-
-/*
- * Get and enable the IOMMU clocks so that we can make
- * sure they stay on the entire duration so that we can
- * safely change the pagetable from the GPU
- */
-static void get_iommu_clocks(struct msm_iommu *iommu, struct device *dev)
+static void iommu_get_clocks(struct msm_iommu *iommu, struct device *dev)
{
struct property *prop;
const char *name;
int i = 0;
- if (iommu->nr_clocks) {
- enable_iommu_clocks(iommu);
- return;
- }
-
iommu->nr_clocks =
of_property_count_strings(dev->of_node, "clock-names");
- if (iommu->nr_clocks < 0) {
- iommu->nr_clocks = 0;
+ if (iommu->nr_clocks < 0)
return;
- }
if (WARN_ON(iommu->nr_clocks > ARRAY_SIZE(iommu->clocks)))
iommu->nr_clocks = ARRAY_SIZE(iommu->clocks);
@@ -78,11 +46,34 @@ static void get_iommu_clocks(struct msm_iommu *iommu, struct device *dev)
if (i == iommu->nr_clocks)
break;
- iommu->clocks[i] = clk_get(dev, name);
- i++;
+ iommu->clocks[i++] = clk_get(dev, name);
+ }
+}
+
+
+static void msm_iommu_clocks_enable(struct msm_mmu *mmu)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
+ int i;
+
+ if (!iommu->nr_clocks)
+ iommu_get_clocks(iommu, mmu->dev->parent);
+
+ for (i = 0; i < iommu->nr_clocks; i++) {
+ if (iommu->clocks[i])
+ clk_prepare_enable(iommu->clocks[i]);
}
+}
- enable_iommu_clocks(iommu);
+static void msm_iommu_clocks_disable(struct msm_mmu *mmu)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
+ int i;
+
+ for (i = 0; i < iommu->nr_clocks; i++) {
+ if (iommu->clocks[i])
+ clk_disable_unprepare(iommu->clocks[i]);
+ }
}
static int msm_iommu_attach(struct msm_mmu *mmu, const char **names,
@@ -103,16 +94,12 @@ static int msm_iommu_attach_user(struct msm_mmu *mmu, const char **names,
iommu->allow_dynamic = !iommu_domain_set_attr(iommu->domain,
DOMAIN_ATTR_ENABLE_TTBR1, &val) ? true : false;
- get_iommu_clocks(iommu, mmu->dev->parent);
-
/* Mark the GPU as I/O coherent if it is supported */
iommu->is_coherent = of_dma_is_coherent(mmu->dev->of_node);
ret = iommu_attach_device(iommu->domain, mmu->dev);
- if (ret) {
- disable_iommu_clocks(iommu);
+ if (ret)
return ret;
- }
/*
* Get the context bank for the base domain; this will be shared with
@@ -160,8 +147,6 @@ static void msm_iommu_detach(struct msm_mmu *mmu)
struct msm_iommu *iommu = to_msm_iommu(mmu);
iommu_detach_device(iommu->domain, mmu->dev);
-
- disable_iommu_clocks(iommu);
}
static void msm_iommu_detach_dynamic(struct msm_mmu *mmu)
@@ -261,6 +246,8 @@ static const struct msm_mmu_funcs user_funcs = {
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
.destroy = msm_iommu_destroy,
+ .enable = msm_iommu_clocks_enable,
+ .disable = msm_iommu_clocks_disable,
};
static const struct msm_mmu_funcs dynamic_funcs = {
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 0292a9ae1d33..8be3cefd686d 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -43,6 +43,8 @@ struct msm_mmu_funcs {
void (*unmap)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
void *priv);
void (*destroy)(struct msm_mmu *mmu);
+ void (*enable)(struct msm_mmu *mmu);
+ void (*disable)(struct msm_mmu *mmu);
};
struct msm_mmu {
@@ -68,4 +70,16 @@ struct msm_mmu *msm_iommu_new(struct device *parent,
/* Create a new dynamic domain for GPU */
struct msm_mmu *msm_iommu_new_dynamic(struct msm_mmu *orig);
+static inline void msm_mmu_enable(struct msm_mmu *mmu)
+{
+ if (mmu->funcs->enable)
+ mmu->funcs->enable(mmu);
+}
+
+static inline void msm_mmu_disable(struct msm_mmu *mmu)
+{
+ if (mmu->funcs->disable)
+ mmu->funcs->disable(mmu);
+}
+
#endif /* __MSM_MMU_H__ */