drm/msm: Use idr_preload()
authorRob Clark <robdclark@chromium.org>
Mon, 20 Mar 2023 14:43:33 +0000 (07:43 -0700)
committerRob Clark <robdclark@chromium.org>
Sat, 25 Mar 2023 23:31:44 +0000 (16:31 -0700)
Avoid allocation under idr_lock, to prevent deadlock against the
job_free() path (which runs on same thread as job_run(), which makes
it also part of the fence-signaling path.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Patchwork: https://patchwork.freedesktop.org/patch/527847/
Link: https://lore.kernel.org/r/20230320144356.803762-12-robdclark@gmail.com
drivers/gpu/drm/msm/msm_gem_submit.c

index 513c5d57079226c014716cd79544696ea3dca710..89375c2e422bed98548e56ee80d24e2ed33dce88 100644 (file)
@@ -882,6 +882,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 
        submit->nr_cmds = i;
 
+       idr_preload(GFP_KERNEL);
+
        spin_lock(&queue->idr_lock);
 
        /*
@@ -893,6 +895,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) &&
                        idr_find(&queue->fence_idr, args->fence)) {
                spin_unlock(&queue->idr_lock);
+               idr_preload_end();
                ret = -EINVAL;
                goto out;
        }
@@ -910,7 +913,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                submit->fence_id = args->fence;
                ret = idr_alloc_u32(&queue->fence_idr, submit->user_fence,
                                    &submit->fence_id, submit->fence_id,
-                                   GFP_KERNEL);
+                                   GFP_NOWAIT);
                /*
                 * We've already validated that the fence_id slot is valid,
                 * so if idr_alloc_u32 failed, it is a kernel bug
@@ -923,10 +926,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                 */
                submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
                                                    submit->user_fence, 1,
-                                                   INT_MAX, GFP_KERNEL);
+                                                   INT_MAX, GFP_NOWAIT);
        }
 
        spin_unlock(&queue->idr_lock);
+       idr_preload_end();
 
        if (submit->fence_id < 0) {
                ret = submit->fence_id;