]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/msm: Track "seqno" fences by idr
authorRob Clark <robdclark@chromium.org>
Wed, 28 Jul 2021 01:06:12 +0000 (18:06 -0700)
committerRob Clark <robdclark@chromium.org>
Wed, 28 Jul 2021 01:09:18 +0000 (18:09 -0700)
Previously the (non-fd) fence returned from submit ioctl was a raw
seqno, which is scoped to the ring.  But from UABI standpoint, the
ioctls related to seqno fences all specify a submitqueue.  We can
take advantage of that to replace the seqno fences with a cyclic idr
handle.

This is in preperation for moving to drm scheduler, at which point
the submit ioctl will return after queuing the submit job to the
scheduler, but before the submit is written into the ring (and
therefore before a ring seqno has been assigned).  Which means we
need to replace the dma_fence that userspace may need to wait on
with a scheduler fence.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Acked-by: Christian König <christian.koenig@amd.com>
Link: https://lore.kernel.org/r/20210728010632.2633470-8-robdclark@gmail.com
Signed-off-by: Rob Clark <robdclark@chromium.org>
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_fence.c
drivers/gpu/drm/msm/msm_fence.h
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_submitqueue.c

index 9b8fa2ad0d8407e681f7b5371e0bdb4ef9c9b09c..1594ae39d54fe46b9c3b7de542a58eb40ac8560e 100644 (file)
@@ -911,6 +911,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *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) {
@@ -925,10 +926,35 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
        if (!queue)
                return -ENOENT;
 
-       ret = msm_wait_fence(gpu->rb[queue->prio]->fctx, args->fence, &timeout,
-               true);
+       /*
+        * Map submitqueue scoped "seqno" (which is actually an idr key)
+        * back to underlying dma-fence
+        *
+        * The fence is removed from the fence_idr when the submit is
+        * retired, so if the fence is not found it means there is nothing
+        * to wait for
+        */
+       ret = mutex_lock_interruptible(&queue->lock);
+       if (ret)
+               return ret;
+       fence = idr_find(&queue->fence_idr, args->fence);
+       if (fence)
+               fence = dma_fence_get_rcu(fence);
+       mutex_unlock(&queue->lock);
+
+       if (!fence)
+               return 0;
 
+       ret = dma_fence_wait_timeout(fence, true, timeout_to_jiffies(&timeout));
+       if (ret == 0) {
+               ret = -ETIMEDOUT;
+       } else if (ret != -ERESTARTSYS) {
+               ret = 0;
+       }
+
+       dma_fence_put(fence);
        msm_submitqueue_put(queue);
+
        return ret;
 }
 
index b92a9091a1e2b31763bea0b98d91fc69d1fd5db7..f2cece542c3f72d5f307c9a33841103bdae1fa4c 100644 (file)
@@ -24,7 +24,6 @@ msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr,
        strncpy(fctx->name, name, sizeof(fctx->name));
        fctx->context = dma_fence_context_alloc(1);
        fctx->fenceptr = fenceptr;
-       init_waitqueue_head(&fctx->event);
        spin_lock_init(&fctx->spinlock);
 
        return fctx;
@@ -45,53 +44,12 @@ static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fenc
                (int32_t)(*fctx->fenceptr - fence) >= 0;
 }
 
-/* legacy path for WAIT_FENCE ioctl: */
-int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
-               ktime_t *timeout, bool interruptible)
-{
-       int ret;
-
-       if (fence > fctx->last_fence) {
-               DRM_ERROR_RATELIMITED("%s: waiting on invalid fence: %u (of %u)\n",
-                               fctx->name, fence, fctx->last_fence);
-               return -EINVAL;
-       }
-
-       if (!timeout) {
-               /* no-wait: */
-               ret = fence_completed(fctx, fence) ? 0 : -EBUSY;
-       } else {
-               unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
-
-               if (interruptible)
-                       ret = wait_event_interruptible_timeout(fctx->event,
-                               fence_completed(fctx, fence),
-                               remaining_jiffies);
-               else
-                       ret = wait_event_timeout(fctx->event,
-                               fence_completed(fctx, fence),
-                               remaining_jiffies);
-
-               if (ret == 0) {
-                       DBG("timeout waiting for fence: %u (completed: %u)",
-                                       fence, fctx->completed_fence);
-                       ret = -ETIMEDOUT;
-               } else if (ret != -ERESTARTSYS) {
-                       ret = 0;
-               }
-       }
-
-       return ret;
-}
-
 /* called from workqueue */
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
 {
        spin_lock(&fctx->spinlock);
        fctx->completed_fence = max(fence, fctx->completed_fence);
        spin_unlock(&fctx->spinlock);
-
-       wake_up_all(&fctx->event);
 }
 
 struct msm_fence {
index 6ab97062ff1ab4e97648a8f0a22ca88a0f03d10b..4783db528bccec62eebf01156bbec9eac0ff2ac1 100644 (file)
@@ -49,7 +49,6 @@ struct msm_fence_context {
         */
        volatile uint32_t *fenceptr;
 
-       wait_queue_head_t event;
        spinlock_t spinlock;
 };
 
@@ -57,8 +56,6 @@ struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
                volatile uint32_t *fenceptr, const char *name);
 void msm_fence_context_free(struct msm_fence_context *fctx);
 
-int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
-               ktime_t *timeout, bool interruptible);
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
 
 struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx);
index da3af702a6c899df49b536762b1a6e162ed19b52..e0579abda5b9fa8771a3a93797606f74bffcf7c3 100644 (file)
@@ -320,6 +320,7 @@ struct msm_gem_submit {
        struct ww_acquire_ctx ticket;
        uint32_t seqno;         /* Sequence number of the submit on the ring */
        struct dma_fence *fence;
+       int fence_id;       /* key into queue->fence_idr */
        struct msm_gpu_submitqueue *queue;
        struct pid *pid;    /* submitting process */
        bool fault_dumped;  /* Limit devcoredump dumping to one per submit */
index 4f02fa3c78f9943fa08581b3f91f137ed7e0204b..f6f595aae2c5829de48f2ede6235097319ef1c01 100644 (file)
@@ -68,7 +68,14 @@ void __msm_gem_submit_destroy(struct kref *kref)
                        container_of(kref, struct msm_gem_submit, ref);
        unsigned i;
 
+       if (submit->fence_id) {
+               mutex_lock(&submit->queue->lock);
+               idr_remove(&submit->queue->fence_idr, submit->fence_id);
+               mutex_unlock(&submit->queue->lock);
+       }
+
        dma_fence_put(submit->fence);
+
        put_pid(submit->pid);
        msm_submitqueue_put(submit->queue);
 
@@ -872,6 +879,20 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                goto out;
        }
 
+       /*
+        * Allocate an id which can be used by WAIT_FENCE ioctl to map back
+        * to the underlying fence.
+        */
+       mutex_lock(&queue->lock);
+       submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
+                       submit->fence, 0, INT_MAX, GFP_KERNEL);
+       mutex_unlock(&queue->lock);
+       if (submit->fence_id < 0) {
+               ret = submit->fence_id = 0;
+               submit->fence_id = 0;
+               goto out;
+       }
+
        if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
                struct sync_file *sync_file = sync_file_create(submit->fence);
                if (!sync_file) {
@@ -886,7 +907,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 
        msm_gpu_submit(gpu, submit);
 
-       args->fence = submit->fence->seqno;
+       args->fence = submit->fence_id;
 
        msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
        msm_process_post_deps(post_deps, args->nr_out_syncobjs,
index 96efcb31e5021f435e0bad6b65b98e6b772f3e61..5796272525409f586e8cc235eee1c2c8b4c6d851 100644 (file)
@@ -263,6 +263,9 @@ struct msm_gpu_perfcntr {
  *             which set of pgtables do submits jobs associated with the
  *             submitqueue use)
  * @node:      node in the context's list of submitqueues
+ * @fence_idr: maps fence-id to dma_fence for userspace visible fence
+ *             seqno, protected by submitqueue lock
+ * @lock:      submitqueue lock
  * @ref:       reference count
  */
 struct msm_gpu_submitqueue {
@@ -272,6 +275,8 @@ struct msm_gpu_submitqueue {
        int faults;
        struct msm_file_private *ctx;
        struct list_head node;
+       struct idr fence_idr;
+       struct mutex lock;
        struct kref ref;
 };
 
index 9e9fec61d629541a047086bb78e586a5e7c83e05..66f8d0fb38b05cf9dc5f311a457fd8d7d14b23c7 100644 (file)
@@ -12,6 +12,8 @@ void msm_submitqueue_destroy(struct kref *kref)
        struct msm_gpu_submitqueue *queue = container_of(kref,
                struct msm_gpu_submitqueue, ref);
 
+       idr_destroy(&queue->fence_idr);
+
        msm_file_private_put(queue->ctx);
 
        kfree(queue);
@@ -89,6 +91,9 @@ int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx,
        if (id)
                *id = queue->id;
 
+       idr_init(&queue->fence_idr);
+       mutex_init(&queue->lock);
+
        list_add_tail(&queue->node, &ctx->submitqueues);
 
        write_unlock(&ctx->queuelock);