drm/prime: fix error path deadlock fail

There were a couple messed up things about this fail path.
(1) it would drop object_name_lock twice
(2) drm_gem_handle_delete() (in drm_gem_remove_prime_handles())
    needs to grab prime_lock

Reported-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1465500559-17873-1-git-send-email-robdclark@gmail.com
This commit is contained in:
Rob Clark 2016-06-09 15:29:19 -04:00 committed by Daniel Vetter
parent babb24fec1
commit bd6e2732f0
1 changed files with 6 additions and 4 deletions

View File

@ -593,7 +593,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
get_dma_buf(dma_buf); get_dma_buf(dma_buf);
} }
/* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
ret = drm_gem_handle_create_tail(file_priv, obj, handle); ret = drm_gem_handle_create_tail(file_priv, obj, handle);
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
if (ret) if (ret)
@ -601,11 +601,10 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
ret = drm_prime_add_buf_handle(&file_priv->prime, ret = drm_prime_add_buf_handle(&file_priv->prime,
dma_buf, *handle); dma_buf, *handle);
mutex_unlock(&file_priv->prime.lock);
if (ret) if (ret)
goto fail; goto fail;
mutex_unlock(&file_priv->prime.lock);
dma_buf_put(dma_buf); dma_buf_put(dma_buf);
return 0; return 0;
@ -615,11 +614,14 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
* to detach.. which seems ok.. * to detach.. which seems ok..
*/ */
drm_gem_handle_delete(file_priv, *handle); drm_gem_handle_delete(file_priv, *handle);
dma_buf_put(dma_buf);
return ret;
out_unlock: out_unlock:
mutex_unlock(&dev->object_name_lock); mutex_unlock(&dev->object_name_lock);
out_put: out_put:
dma_buf_put(dma_buf);
mutex_unlock(&file_priv->prime.lock); mutex_unlock(&file_priv->prime.lock);
dma_buf_put(dma_buf);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);