drm/etnaviv: lock BOs after all other submit work is done
[sfrench/cifs-2.6.git] / drivers / gpu / drm / etnaviv / etnaviv_gem_submit.c
index 1f8202bca061542a2f0d994d6f2554540809ac90..83339e0335ff8cc52e8fe8877feb6ace56afaac3 100644 (file)
@@ -22,6 +22,7 @@
 #include "etnaviv_gpu.h"
 #include "etnaviv_gem.h"
 #include "etnaviv_perfmon.h"
+#include "etnaviv_sched.h"
 
 /*
  * Cmdstream submission:
@@ -169,29 +170,33 @@ fail:
        return ret;
 }
 
-static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
+static int submit_fence_sync(struct etnaviv_gem_submit *submit)
 {
-       unsigned int context = submit->gpu->fence_context;
        int i, ret = 0;
 
        for (i = 0; i < submit->nr_bos; i++) {
-               struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
-               bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
-               bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
+               struct etnaviv_gem_submit_bo *bo = &submit->bos[i];
+               struct reservation_object *robj = bo->obj->resv;
 
-               ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,
-                                                explicit);
-               if (ret)
-                       break;
-       }
+               if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) {
+                       ret = reservation_object_reserve_shared(robj);
+                       if (ret)
+                               return ret;
+               }
+
+               if (submit->flags & ETNA_SUBMIT_NO_IMPLICIT)
+                       continue;
+
+               if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
+                       ret = reservation_object_get_fences_rcu(robj, &bo->excl,
+                                                               &bo->nr_shared,
+                                                               &bo->shared);
+                       if (ret)
+                               return ret;
+               } else {
+                       bo->excl = reservation_object_get_excl_rcu(robj);
+               }
 
-       if (submit->flags & ETNA_SUBMIT_FENCE_FD_IN) {
-               /*
-                * Wait if the fence is from a foreign context, or if the fence
-                * array contains any fence from a foreign context.
-                */
-               if (!dma_fence_match_context(submit->in_fence, context))
-                       ret = dma_fence_wait(submit->in_fence, true);
        }
 
        return ret;
@@ -381,8 +386,13 @@ static void submit_cleanup(struct kref *kref)
 
        if (submit->in_fence)
                dma_fence_put(submit->in_fence);
-       if (submit->out_fence)
+       if (submit->out_fence) {
+               /* first remove from IDR, so fence can not be found anymore */
+               mutex_lock(&submit->gpu->fence_idr_lock);
+               idr_remove(&submit->gpu->fence_idr, submit->out_fence_id);
+               mutex_unlock(&submit->gpu->fence_idr_lock);
                dma_fence_put(submit->out_fence);
+       }
        kfree(submit->pmrs);
        kfree(submit);
 }
@@ -395,6 +405,7 @@ void etnaviv_submit_put(struct etnaviv_gem_submit *submit)
 int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
                struct drm_file *file)
 {
+       struct etnaviv_file_private *ctx = file->driver_priv;
        struct etnaviv_drm_private *priv = dev->dev_private;
        struct drm_etnaviv_gem_submit *args = data;
        struct drm_etnaviv_gem_submit_reloc *relocs;
@@ -503,10 +514,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
        if (ret)
                goto err_submit_objects;
 
-       ret = submit_lock_objects(submit, &ticket);
-       if (ret)
-               goto err_submit_objects;
-
        if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
                                      relocs, args->nr_relocs)) {
                ret = -EINVAL;
@@ -521,10 +528,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
                }
        }
 
-       ret = submit_fence_sync(submit);
-       if (ret)
-               goto err_submit_objects;
-
        ret = submit_pin_objects(submit);
        if (ret)
                goto err_submit_objects;
@@ -541,7 +544,15 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
        memcpy(submit->cmdbuf.vaddr, stream, args->stream_size);
        submit->cmdbuf.user_size = ALIGN(args->stream_size, 8);
 
-       ret = etnaviv_gpu_submit(gpu, submit);
+       ret = submit_lock_objects(submit, &ticket);
+       if (ret)
+               goto err_submit_objects;
+
+       ret = submit_fence_sync(submit);
+       if (ret)
+               goto err_submit_objects;
+
+       ret = etnaviv_sched_push_job(&ctx->sched_entity[args->pipe], submit);
        if (ret)
                goto err_submit_objects;
 
@@ -563,7 +574,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
        }
 
        args->fence_fd = out_fence_fd;
-       args->fence = submit->out_fence->seqno;
+       args->fence = submit->out_fence_id;
 
 err_submit_objects:
        etnaviv_submit_put(submit);