| From 029b53ab8623e45bb3efd9bbe30f004d3e37ccaf Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 11 Nov 2021 11:24:55 -0800 |
| Subject: drm/msm: Fix wait_fence submitqueue leak |
| |
| From: Rob Clark <robdclark@chromium.org> |
| |
| [ Upstream commit ea0006d390a28012f8187717aea61498b2b341e5 ] |
| |
| 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: a61acbbe9cf8 ("drm/msm: Track "seqno" fences by idr") |
| Signed-off-by: Rob Clark <robdclark@chromium.org> |
| Link: https://lore.kernel.org/r/20211111192457.747899-2-robdclark@gmail.com |
| Signed-off-by: Rob Clark <robdclark@chromium.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpu/drm/msm/msm_drv.c | 49 +++++++++++++++++++++-------------- |
| 1 file changed, 29 insertions(+), 20 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c |
| index d4e09703a87db..4c5661f38dd26 100644 |
| --- a/drivers/gpu/drm/msm/msm_drv.c |
| +++ b/drivers/gpu/drm/msm/msm_drv.c |
| @@ -938,29 +938,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 |
| @@ -972,7 +955,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); |
| @@ -988,6 +971,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; |
| -- |
| 2.33.0 |
| |