aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-07-11 11:59:22 -0400
committerRob Clark <robdclark@gmail.com>2014-08-04 11:55:29 -0400
commita1ad35233345e7ddd9ea3ea7b841432f4723d743 (patch)
tree89fa09c7bfbf0367280bd998c0dfc4508b205776 /drivers/gpu/drm/msm
parent944fc36c31ed685cf8d3d125eb681ae7198f06fc (diff)
drm/msm: fix potential deadlock in gpu init
Somewhere along the way, the firmware loader sprouted another lock dependency, resulting in possible deadlock scenario: &dev->struct_mutex --> &sb->s_type->i_mutex_key#2 --> &mm->mmap_sem which is problematic vs things like gem mmap. So introduce a separate mutex to synchronize gpu init. Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c8
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c13
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c3
3 files changed, 16 insertions, 8 deletions
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 76c1df73e747..655ce5b14ad0 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -95,7 +95,7 @@ int adreno_hw_init(struct msm_gpu *gpu)
95 95
96 DBG("%s", gpu->name); 96 DBG("%s", gpu->name);
97 97
98 ret = msm_gem_get_iova_locked(gpu->rb->bo, gpu->id, &gpu->rb_iova); 98 ret = msm_gem_get_iova(gpu->rb->bo, gpu->id, &gpu->rb_iova);
99 if (ret) { 99 if (ret) {
100 gpu->rb_iova = 0; 100 gpu->rb_iova = 0;
101 dev_err(gpu->dev->dev, "could not map ringbuffer: %d\n", ret); 101 dev_err(gpu->dev->dev, "could not map ringbuffer: %d\n", ret);
@@ -370,8 +370,10 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
370 return ret; 370 return ret;
371 } 371 }
372 372
373 mutex_lock(&drm->struct_mutex);
373 gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs), 374 gpu->memptrs_bo = msm_gem_new(drm, sizeof(*gpu->memptrs),
374 MSM_BO_UNCACHED); 375 MSM_BO_UNCACHED);
376 mutex_unlock(&drm->struct_mutex);
375 if (IS_ERR(gpu->memptrs_bo)) { 377 if (IS_ERR(gpu->memptrs_bo)) {
376 ret = PTR_ERR(gpu->memptrs_bo); 378 ret = PTR_ERR(gpu->memptrs_bo);
377 gpu->memptrs_bo = NULL; 379 gpu->memptrs_bo = NULL;
@@ -379,13 +381,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
379 return ret; 381 return ret;
380 } 382 }
381 383
382 gpu->memptrs = msm_gem_vaddr_locked(gpu->memptrs_bo); 384 gpu->memptrs = msm_gem_vaddr(gpu->memptrs_bo);
383 if (!gpu->memptrs) { 385 if (!gpu->memptrs) {
384 dev_err(drm->dev, "could not vmap memptrs\n"); 386 dev_err(drm->dev, "could not vmap memptrs\n");
385 return -ENOMEM; 387 return -ENOMEM;
386 } 388 }
387 389
388 ret = msm_gem_get_iova_locked(gpu->memptrs_bo, gpu->base.id, 390 ret = msm_gem_get_iova(gpu->memptrs_bo, gpu->base.id,
389 &gpu->memptrs_iova); 391 &gpu->memptrs_iova);
390 if (ret) { 392 if (ret) {
391 dev_err(drm->dev, "could not map memptrs: %d\n", ret); 393 dev_err(drm->dev, "could not map memptrs: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index a2f5bf6da6f3..b447c01ad89c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -181,7 +181,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
181 struct msm_kms *kms; 181 struct msm_kms *kms;
182 int ret; 182 int ret;
183 183
184
185 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 184 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
186 if (!priv) { 185 if (!priv) {
187 dev_err(dev->dev, "failed to allocate private data\n"); 186 dev_err(dev->dev, "failed to allocate private data\n");
@@ -314,13 +313,15 @@ fail:
314 313
315static void load_gpu(struct drm_device *dev) 314static void load_gpu(struct drm_device *dev)
316{ 315{
316 static DEFINE_MUTEX(init_lock);
317 struct msm_drm_private *priv = dev->dev_private; 317 struct msm_drm_private *priv = dev->dev_private;
318 struct msm_gpu *gpu; 318 struct msm_gpu *gpu;
319 319
320 mutex_lock(&init_lock);
321
320 if (priv->gpu) 322 if (priv->gpu)
321 return; 323 goto out;
322 324
323 mutex_lock(&dev->struct_mutex);
324 gpu = a3xx_gpu_init(dev); 325 gpu = a3xx_gpu_init(dev);
325 if (IS_ERR(gpu)) { 326 if (IS_ERR(gpu)) {
326 dev_warn(dev->dev, "failed to load a3xx gpu\n"); 327 dev_warn(dev->dev, "failed to load a3xx gpu\n");
@@ -330,7 +331,9 @@ static void load_gpu(struct drm_device *dev)
330 331
331 if (gpu) { 332 if (gpu) {
332 int ret; 333 int ret;
334 mutex_lock(&dev->struct_mutex);
333 gpu->funcs->pm_resume(gpu); 335 gpu->funcs->pm_resume(gpu);
336 mutex_unlock(&dev->struct_mutex);
334 ret = gpu->funcs->hw_init(gpu); 337 ret = gpu->funcs->hw_init(gpu);
335 if (ret) { 338 if (ret) {
336 dev_err(dev->dev, "gpu hw init failed: %d\n", ret); 339 dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
@@ -340,12 +343,12 @@ static void load_gpu(struct drm_device *dev)
340 /* give inactive pm a chance to kick in: */ 343 /* give inactive pm a chance to kick in: */
341 msm_gpu_retire(gpu); 344 msm_gpu_retire(gpu);
342 } 345 }
343
344 } 346 }
345 347
346 priv->gpu = gpu; 348 priv->gpu = gpu;
347 349
348 mutex_unlock(&dev->struct_mutex); 350out:
351 mutex_unlock(&init_lock);
349} 352}
350 353
351static int msm_open(struct drm_device *dev, struct drm_file *file) 354static int msm_open(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 915240b4b80a..4a0dce587745 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -612,8 +612,11 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
612 } 612 }
613 gpu->id = msm_register_mmu(drm, gpu->mmu); 613 gpu->id = msm_register_mmu(drm, gpu->mmu);
614 614
615
615 /* Create ringbuffer: */ 616 /* Create ringbuffer: */
617 mutex_lock(&drm->struct_mutex);
616 gpu->rb = msm_ringbuffer_new(gpu, ringsz); 618 gpu->rb = msm_ringbuffer_new(gpu, ringsz);
619 mutex_unlock(&drm->struct_mutex);
617 if (IS_ERR(gpu->rb)) { 620 if (IS_ERR(gpu->rb)) {
618 ret = PTR_ERR(gpu->rb); 621 ret = PTR_ERR(gpu->rb);
619 gpu->rb = NULL; 622 gpu->rb = NULL;