aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Viau <sviau@codeaurora.org>2014-06-17 10:32:37 -0400
committerRob Clark <robdclark@gmail.com>2014-06-22 08:32:10 -0400
commit87e956e9be0cdb832e90a4731b620286a8826842 (patch)
treeaae99419fd336809818e4c91a393d89413b29719
parentcf3198c2051a180d0cb469b275b2fb30a0533772 (diff)
drm/msm: fix IOMMU cleanup for -EPROBE_DEFER
If probe fails after IOMMU is attached, we need to detach in order to clean up properly. Before this change, IOMMU faults would occur if the probe failed (-EPROBE_DEFER). Signed-off-by: Stephane Viau <sviau@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c22
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c6
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c21
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h1
5 files changed, 44 insertions, 7 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 42caf7fcb0b9..71510ee26e96 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -20,6 +20,10 @@
20#include "msm_mmu.h" 20#include "msm_mmu.h"
21#include "mdp5_kms.h" 21#include "mdp5_kms.h"
22 22
23static const char *iommu_ports[] = {
24 "mdp_0",
25};
26
23static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev); 27static struct mdp5_platform_config *mdp5_get_config(struct platform_device *dev);
24 28
25static int mdp5_hw_init(struct msm_kms *kms) 29static int mdp5_hw_init(struct msm_kms *kms)
@@ -104,6 +108,12 @@ static void mdp5_preclose(struct msm_kms *kms, struct drm_file *file)
104static void mdp5_destroy(struct msm_kms *kms) 108static void mdp5_destroy(struct msm_kms *kms)
105{ 109{
106 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); 110 struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
111 struct msm_mmu *mmu = mdp5_kms->mmu;
112
113 if (mmu) {
114 mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
115 mmu->funcs->destroy(mmu);
116 }
107 kfree(mdp5_kms); 117 kfree(mdp5_kms);
108} 118}
109 119
@@ -216,10 +226,6 @@ fail:
216 return ret; 226 return ret;
217} 227}
218 228
219static const char *iommu_ports[] = {
220 "mdp_0",
221};
222
223static int get_clk(struct platform_device *pdev, struct clk **clkp, 229static int get_clk(struct platform_device *pdev, struct clk **clkp,
224 const char *name) 230 const char *name)
225{ 231{
@@ -317,17 +323,23 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
317 mmu = msm_iommu_new(dev, config->iommu); 323 mmu = msm_iommu_new(dev, config->iommu);
318 if (IS_ERR(mmu)) { 324 if (IS_ERR(mmu)) {
319 ret = PTR_ERR(mmu); 325 ret = PTR_ERR(mmu);
326 dev_err(dev->dev, "failed to init iommu: %d\n", ret);
320 goto fail; 327 goto fail;
321 } 328 }
329
322 ret = mmu->funcs->attach(mmu, iommu_ports, 330 ret = mmu->funcs->attach(mmu, iommu_ports,
323 ARRAY_SIZE(iommu_ports)); 331 ARRAY_SIZE(iommu_ports));
324 if (ret) 332 if (ret) {
333 dev_err(dev->dev, "failed to attach iommu: %d\n", ret);
334 mmu->funcs->destroy(mmu);
325 goto fail; 335 goto fail;
336 }
326 } else { 337 } else {
327 dev_info(dev->dev, "no iommu, fallback to phys " 338 dev_info(dev->dev, "no iommu, fallback to phys "
328 "contig buffers for scanout\n"); 339 "contig buffers for scanout\n");
329 mmu = NULL; 340 mmu = NULL;
330 } 341 }
342 mdp5_kms->mmu = mmu;
331 343
332 mdp5_kms->id = msm_register_mmu(dev, mmu); 344 mdp5_kms->id = msm_register_mmu(dev, mmu);
333 if (mdp5_kms->id < 0) { 345 if (mdp5_kms->id < 0) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index c8b1a2522c25..6e981b692d1d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -33,6 +33,7 @@ struct mdp5_kms {
33 33
34 /* mapper-id used to request GEM buffer mapped for scanout: */ 34 /* mapper-id used to request GEM buffer mapped for scanout: */
35 int id; 35 int id;
36 struct msm_mmu *mmu;
36 37
37 /* for tracking smp allocation amongst pipes: */ 38 /* for tracking smp allocation amongst pipes: */
38 mdp5_smp_state_t smp_state; 39 mdp5_smp_state_t smp_state;
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index bb8026daebc9..690d7e7b6d1e 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -278,6 +278,7 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
278 uint32_t *iova) 278 uint32_t *iova)
279{ 279{
280 struct msm_gem_object *msm_obj = to_msm_bo(obj); 280 struct msm_gem_object *msm_obj = to_msm_bo(obj);
281 struct drm_device *dev = obj->dev;
281 int ret = 0; 282 int ret = 0;
282 283
283 if (!msm_obj->domain[id].iova) { 284 if (!msm_obj->domain[id].iova) {
@@ -285,6 +286,11 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
285 struct msm_mmu *mmu = priv->mmus[id]; 286 struct msm_mmu *mmu = priv->mmus[id];
286 struct page **pages = get_pages(obj); 287 struct page **pages = get_pages(obj);
287 288
289 if (!mmu) {
290 dev_err(dev->dev, "null MMU pointer\n");
291 return -EINVAL;
292 }
293
288 if (IS_ERR(pages)) 294 if (IS_ERR(pages))
289 return PTR_ERR(pages); 295 return PTR_ERR(pages);
290 296
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 198ed848fec7..4b2ad9181edf 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -28,7 +28,7 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
28 unsigned long iova, int flags, void *arg) 28 unsigned long iova, int flags, void *arg)
29{ 29{
30 DBG("*** fault: iova=%08lx, flags=%d", iova, flags); 30 DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
31 return 0; 31 return -ENOSYS;
32} 32}
33 33
34static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) 34static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
@@ -40,8 +40,10 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
40 for (i = 0; i < cnt; i++) { 40 for (i = 0; i < cnt; i++) {
41 struct device *msm_iommu_get_ctx(const char *ctx_name); 41 struct device *msm_iommu_get_ctx(const char *ctx_name);
42 struct device *ctx = msm_iommu_get_ctx(names[i]); 42 struct device *ctx = msm_iommu_get_ctx(names[i]);
43 if (IS_ERR_OR_NULL(ctx)) 43 if (IS_ERR_OR_NULL(ctx)) {
44 dev_warn(dev->dev, "couldn't get %s context", names[i]);
44 continue; 45 continue;
46 }
45 ret = iommu_attach_device(iommu->domain, ctx); 47 ret = iommu_attach_device(iommu->domain, ctx);
46 if (ret) { 48 if (ret) {
47 dev_warn(dev->dev, "could not attach iommu to %s", names[i]); 49 dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
@@ -52,6 +54,20 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
52 return 0; 54 return 0;
53} 55}
54 56
57static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt)
58{
59 struct msm_iommu *iommu = to_msm_iommu(mmu);
60 int i;
61
62 for (i = 0; i < cnt; i++) {
63 struct device *msm_iommu_get_ctx(const char *ctx_name);
64 struct device *ctx = msm_iommu_get_ctx(names[i]);
65 if (IS_ERR_OR_NULL(ctx))
66 continue;
67 iommu_detach_device(iommu->domain, ctx);
68 }
69}
70
55static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, 71static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
56 struct sg_table *sgt, unsigned len, int prot) 72 struct sg_table *sgt, unsigned len, int prot)
57{ 73{
@@ -127,6 +143,7 @@ static void msm_iommu_destroy(struct msm_mmu *mmu)
127 143
128static const struct msm_mmu_funcs funcs = { 144static const struct msm_mmu_funcs funcs = {
129 .attach = msm_iommu_attach, 145 .attach = msm_iommu_attach,
146 .detach = msm_iommu_detach,
130 .map = msm_iommu_map, 147 .map = msm_iommu_map,
131 .unmap = msm_iommu_unmap, 148 .unmap = msm_iommu_unmap,
132 .destroy = msm_iommu_destroy, 149 .destroy = msm_iommu_destroy,
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index 030324482b4a..21da6d154f71 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -22,6 +22,7 @@
22 22
23struct msm_mmu_funcs { 23struct msm_mmu_funcs {
24 int (*attach)(struct msm_mmu *mmu, const char **names, int cnt); 24 int (*attach)(struct msm_mmu *mmu, const char **names, int cnt);
25 void (*detach)(struct msm_mmu *mmu, const char **names, int cnt);
25 int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, 26 int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
26 unsigned len, int prot); 27 unsigned len, int prot);
27 int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt, 28 int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,