aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/msm_drv.c
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/msm_drv.c
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/msm_drv.c')
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c13
1 files changed, 8 insertions, 5 deletions
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)
struct msm_kms *kms;
int ret;
-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(dev->dev, "failed to allocate private data\n");
@@ -314,13 +313,15 @@ fail:
static void load_gpu(struct drm_device *dev)
{
+ static DEFINE_MUTEX(init_lock);
struct msm_drm_private *priv = dev->dev_private;
struct msm_gpu *gpu;
+ mutex_lock(&init_lock);
+
if (priv->gpu)
- return;
+ goto out;
- mutex_lock(&dev->struct_mutex);
gpu = a3xx_gpu_init(dev);
if (IS_ERR(gpu)) {
dev_warn(dev->dev, "failed to load a3xx gpu\n");
@@ -330,7 +331,9 @@ static void load_gpu(struct drm_device *dev)
if (gpu) {
int ret;
+ mutex_lock(&dev->struct_mutex);
gpu->funcs->pm_resume(gpu);
+ mutex_unlock(&dev->struct_mutex);
ret = gpu->funcs->hw_init(gpu);
if (ret) {
dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
@@ -340,12 +343,12 @@ static void load_gpu(struct drm_device *dev)
/* give inactive pm a chance to kick in: */
msm_gpu_retire(gpu);
}
-
}
priv->gpu = gpu;
- mutex_unlock(&dev->struct_mutex);
+out:
+ mutex_unlock(&init_lock);
}
static int msm_open(struct drm_device *dev, struct drm_file *file)