summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoungJun Cho <yj44.cho@samsung.com>2013-06-26 10:21:42 +0900
committerChanho Park <chanho61.park@samsung.com>2014-11-21 19:12:23 +0900
commit63e666b5839ebeaea4a777433c954239434e941f (patch)
treee8c4be4612ae6e5e876fd026b529d781711f78c3
parent8045d949a6f04150c46005407439839ccd7cc404 (diff)
downloadlinux-3.10-63e666b5839ebeaea4a777433c954239434e941f.tar.gz
linux-3.10-63e666b5839ebeaea4a777433c954239434e941f.tar.bz2
linux-3.10-63e666b5839ebeaea4a777433c954239434e941f.zip
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>
-rw-r--r--drivers/gpu/drm/drm_prime.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 3d882bdcde8..20e09329b43 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -130,6 +130,21 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf,
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,
enum dma_data_direction dir)
{
@@ -322,15 +337,25 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
if (ret)
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);
return 0;
out_have_obj:
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;
+fail_rm_handle:
+ drm_prime_remove_buf_handle_locked(&file_priv->prime, buf);
fail_put_dmabuf:
/* clear NOT to be checked when releasing dma_buf */
obj->export_dma_buf = NULL;
@@ -601,16 +626,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)
{
- struct drm_prime_member *member, *safe;
-
mutex_lock(&prime_fpriv->lock);
- 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);
- }
- }
+ drm_prime_remove_buf_handle_locked(prime_fpriv, dma_buf);
mutex_unlock(&prime_fpriv->lock);
}
EXPORT_SYMBOL(drm_prime_remove_buf_handle);