diff options
author | Rob Clark <robdclark@gmail.com> | 2014-07-11 11:59:22 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2014-08-04 11:55:29 -0400 |
commit | a1ad35233345e7ddd9ea3ea7b841432f4723d743 (patch) | |
tree | 89fa09c7bfbf0367280bd998c0dfc4508b205776 /drivers/gpu/drm/msm | |
parent | 944fc36c31ed685cf8d3d125eb681ae7198f06fc (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.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 3 |
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 | ||
315 | static void load_gpu(struct drm_device *dev) | 314 | static 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); | 350 | out: |
351 | mutex_unlock(&init_lock); | ||
349 | } | 352 | } |
350 | 353 | ||
351 | static int msm_open(struct drm_device *dev, struct drm_file *file) | 354 | static 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; |