drm/prime: add return check for dma_buf_fd
authorYoungJun Cho <yj44.cho@samsung.com>
Wed, 26 Jun 2013 01:21:42 +0000 (10:21 +0900)
committerDave Airlie <airlied@redhat.com>
Fri, 28 Jun 2013 04:43:04 +0000 (14:43 +1000)
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>
drivers/gpu/drm/drm_prime.c

index 117ffe32a7afba9b1b8e58665c45221bfc806775..52709f2171fb7d71f1964dcb62c2adeed6d2d62d 100644 (file)
@@ -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)
 {
@@ -321,15 +336,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;
@@ -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)
 {
-       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);