drm/prime: add return check for dma_buf_fd

The dma_buf_fd() can return error when it fails to prepare fd,
so the dma_buf needs to be put.

Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
YoungJun Cho 2013-06-26 10:21:42 +09:00 committed by Dave Airlie
parent ce92e3c961
commit da34242e5e

View File

@ -130,6 +130,21 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf,
attach->priv = NULL; attach->priv = NULL;
} }
static void drm_prime_remove_buf_handle_locked(
struct drm_prime_file_private *prime_fpriv,
struct dma_buf *dma_buf)
{
struct drm_prime_member *member, *safe;
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
if (member->dma_buf == dma_buf) {
dma_buf_put(dma_buf);
list_del(&member->entry);
kfree(member);
}
}
}
static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
@ -321,15 +336,25 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
if (ret) if (ret)
goto fail_put_dmabuf; goto fail_put_dmabuf;
*prime_fd = dma_buf_fd(buf, flags); ret = dma_buf_fd(buf, flags);
if (ret < 0)
goto fail_rm_handle;
*prime_fd = ret;
mutex_unlock(&file_priv->prime.lock); mutex_unlock(&file_priv->prime.lock);
return 0; return 0;
out_have_obj: out_have_obj:
get_dma_buf(dmabuf); get_dma_buf(dmabuf);
*prime_fd = dma_buf_fd(dmabuf, flags); ret = dma_buf_fd(dmabuf, flags);
if (ret < 0)
dma_buf_put(dmabuf);
else
*prime_fd = ret;
goto out; goto out;
fail_rm_handle:
drm_prime_remove_buf_handle_locked(&file_priv->prime, buf);
fail_put_dmabuf: fail_put_dmabuf:
/* clear NOT to be checked when releasing dma_buf */ /* clear NOT to be checked when releasing dma_buf */
obj->export_dma_buf = NULL; obj->export_dma_buf = NULL;
@ -600,16 +625,8 @@ EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
{ {
struct drm_prime_member *member, *safe;
mutex_lock(&prime_fpriv->lock); mutex_lock(&prime_fpriv->lock);
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { drm_prime_remove_buf_handle_locked(prime_fpriv, dma_buf);
if (member->dma_buf == dma_buf) {
dma_buf_put(dma_buf);
list_del(&member->entry);
kfree(member);
}
}
mutex_unlock(&prime_fpriv->lock); mutex_unlock(&prime_fpriv->lock);
} }
EXPORT_SYMBOL(drm_prime_remove_buf_handle); EXPORT_SYMBOL(drm_prime_remove_buf_handle);