Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit da34242e authored by YoungJun Cho's avatar YoungJun Cho Committed by Dave Airlie
Browse files

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: default avatarYoungJun Cho <yj44.cho@samsung.com>
Signed-off-by: default avatarSeung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent ce92e3c9
Loading
Loading
Loading
Loading
+28 −11
Original line number Diff line number Diff line
@@ -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);