Commit ea0006d3 authored by Rob Clark's avatar Rob Clark
Browse files

drm/msm: Fix wait_fence submitqueue leak



We weren't dropping the submitqueue reference in all paths.  In
particular, when the fence has already been signalled. Split out
a helper to simplify handling this in the various different return
paths.

Fixes: a61acbbe ("drm/msm: Track "seqno" fences by idr")
Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
Link: https://lore.kernel.org/r/20211111192457.747899-2-robdclark@gmail.com


Signed-off-by: default avatarRob Clark <robdclark@chromium.org>
parent 3466d9e2
Loading
Loading
Loading
Loading
+29 −20
Original line number Diff line number Diff line
@@ -967,29 +967,12 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
	return ret;
}

static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
		struct drm_file *file)
static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id,
		      ktime_t timeout)
{
	struct msm_drm_private *priv = dev->dev_private;
	struct drm_msm_wait_fence *args = data;
	ktime_t timeout = to_ktime(args->timeout);
	struct msm_gpu_submitqueue *queue;
	struct msm_gpu *gpu = priv->gpu;
	struct dma_fence *fence;
	int ret;

	if (args->pad) {
		DRM_ERROR("invalid pad: %08x\n", args->pad);
		return -EINVAL;
	}

	if (!gpu)
		return 0;

	queue = msm_submitqueue_get(file->driver_priv, args->queueid);
	if (!queue)
		return -ENOENT;

	/*
	 * Map submitqueue scoped "seqno" (which is actually an idr key)
	 * back to underlying dma-fence
@@ -1001,7 +984,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
	ret = mutex_lock_interruptible(&queue->lock);
	if (ret)
		return ret;
	fence = idr_find(&queue->fence_idr, args->fence);
	fence = idr_find(&queue->fence_idr, fence_id);
	if (fence)
		fence = dma_fence_get_rcu(fence);
	mutex_unlock(&queue->lock);
@@ -1017,6 +1000,32 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
	}

	dma_fence_put(fence);

	return ret;
}

static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
		struct drm_file *file)
{
	struct msm_drm_private *priv = dev->dev_private;
	struct drm_msm_wait_fence *args = data;
	struct msm_gpu_submitqueue *queue;
	int ret;

	if (args->pad) {
		DRM_ERROR("invalid pad: %08x\n", args->pad);
		return -EINVAL;
	}

	if (!priv->gpu)
		return 0;

	queue = msm_submitqueue_get(file->driver_priv, args->queueid);
	if (!queue)
		return -ENOENT;

	ret = wait_fence(queue, args->fence, to_ktime(args->timeout));

	msm_submitqueue_put(queue);

	return ret;