Merge remote-tracking branches 'spi/fix/bcm63xx', 'spi/fix/doc', 'spi/fix/mediatek...
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_cs.c
index 2ae73d5232dda6319a5581b057073dba3c1e1a15..1d44d508d4d4f50b249104b4aabc9a6cbab83e61 100644 (file)
@@ -439,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
        return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
 }
 
-static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
+/**
+ * cs_parser_fini() - clean parser states
+ * @parser:    parser structure holding parsing context.
+ * @error:     error number
+ *
+ * If error is set than unvalidate buffer, otherwise just free memory
+ * used by parsing context.
+ **/
+static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
 {
+       unsigned i;
+
        if (!error) {
                /* Sort the buffer list from the smallest to largest buffer,
                 * which affects the order of buffers in the LRU list.
@@ -455,17 +465,13 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err
                list_sort(NULL, &parser->validated, cmp_size_smaller_first);
 
                ttm_eu_fence_buffer_objects(&parser->ticket,
-                               &parser->validated,
-                               &parser->ibs[parser->num_ibs-1].fence->base);
+                                           &parser->validated,
+                                           parser->fence);
        } else if (backoff) {
                ttm_eu_backoff_reservation(&parser->ticket,
                                           &parser->validated);
        }
-}
-
-static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
-{
-       unsigned i;
+       fence_put(parser->fence);
 
        if (parser->ctx)
                amdgpu_ctx_put(parser->ctx);
@@ -484,20 +490,6 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
                drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
 }
 
-/**
- * cs_parser_fini() - clean parser states
- * @parser:    parser structure holding parsing context.
- * @error:     error number
- *
- * If error is set than unvalidate buffer, otherwise just free memory
- * used by parsing context.
- **/
-static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
-{
-       amdgpu_cs_parser_fini_early(parser, error, backoff);
-       amdgpu_cs_parser_fini_late(parser);
-}
-
 static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
                                   struct amdgpu_vm *vm)
 {
@@ -582,15 +574,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
        }
 
        r = amdgpu_bo_vm_update_pte(parser, vm);
-       if (r) {
-               goto out;
-       }
-       amdgpu_cs_sync_rings(parser);
-       if (!amdgpu_enable_scheduler)
-               r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
-                                      parser->filp);
+       if (!r)
+               amdgpu_cs_sync_rings(parser);
 
-out:
        return r;
 }
 
@@ -798,8 +784,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
        struct amdgpu_device *adev = dev->dev_private;
        union drm_amdgpu_cs *cs = data;
-       struct amdgpu_fpriv *fpriv = filp->driver_priv;
-       struct amdgpu_vm *vm = &fpriv->vm;
        struct amdgpu_cs_parser parser = {};
        bool reserved_buffers = false;
        int i, r;
@@ -817,7 +801,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                r = amdgpu_cs_handle_lockup(adev, r);
                return r;
        }
-       mutex_lock(&vm->mutex);
        r = amdgpu_cs_parser_relocs(&parser);
        if (r == -ENOMEM)
                DRM_ERROR("Not enough memory for command submission!\n");
@@ -845,8 +828,9 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                goto out;
 
        if (amdgpu_enable_scheduler && parser.num_ibs) {
-               struct amdgpu_job *job;
                struct amdgpu_ring * ring = parser.ibs->ring;
+               struct amd_sched_fence *fence;
+               struct amdgpu_job *job;
 
                job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
                if (!job) {
@@ -857,48 +841,50 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                job->base.sched = &ring->sched;
                job->base.s_entity = &parser.ctx->rings[ring->idx].entity;
                job->adev = parser.adev;
+               job->owner = parser.filp;
+               job->free_job = amdgpu_cs_free_job;
+
                job->ibs = parser.ibs;
                job->num_ibs = parser.num_ibs;
-               job->base.owner = parser.filp;
-               mutex_init(&job->job_lock);
+               parser.ibs = NULL;
+               parser.num_ibs = 0;
+
                if (job->ibs[job->num_ibs - 1].user) {
                        job->uf = parser.uf;
                        job->ibs[job->num_ibs - 1].user = &job->uf;
                        parser.uf.bo = NULL;
                }
 
-               parser.ibs = NULL;
-               parser.num_ibs = 0;
-
-               job->free_job = amdgpu_cs_free_job;
-               mutex_lock(&job->job_lock);
-               r = amd_sched_entity_push_job(&job->base);
-               if (r) {
-                       mutex_unlock(&job->job_lock);
+               fence = amd_sched_fence_create(job->base.s_entity,
+                                              parser.filp);
+               if (!fence) {
+                       r = -ENOMEM;
                        amdgpu_cs_free_job(job);
                        kfree(job);
                        goto out;
                }
-               cs->out.handle =
-                       amdgpu_ctx_add_fence(parser.ctx, ring,
-                                            &job->base.s_fence->base);
+               job->base.s_fence = fence;
+               parser.fence = fence_get(&fence->base);
+
+               cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring,
+                                                     &fence->base);
                job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
 
-               list_sort(NULL, &parser.validated, cmp_size_smaller_first);
-               ttm_eu_fence_buffer_objects(&parser.ticket,
-                               &parser.validated,
-                               &job->base.s_fence->base);
                trace_amdgpu_cs_ioctl(job);
-               mutex_unlock(&job->job_lock);
-               amdgpu_cs_parser_fini_late(&parser);
-               mutex_unlock(&vm->mutex);
-               return 0;
+               amd_sched_entity_push_job(&job->base);
+
+       } else {
+               struct amdgpu_fence *fence;
+
+               r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs,
+                                      parser.filp);
+               fence = parser.ibs[parser.num_ibs - 1].fence;
+               parser.fence = fence_get(&fence->base);
+               cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
        }
 
-       cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
 out:
        amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
-       mutex_unlock(&vm->mutex);
        r = amdgpu_cs_handle_lockup(adev, r);
        return r;
 }