Merge tag 'linux-kselftest-kunit-5.10-rc1' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / i915_vma.c
index bc64f77..ffb5287 100644 (file)
@@ -291,6 +291,8 @@ i915_vma_instance(struct drm_i915_gem_object *obj,
 
 struct i915_vma_work {
        struct dma_fence_work base;
+       struct i915_address_space *vm;
+       struct i915_vm_pt_stash stash;
        struct i915_vma *vma;
        struct drm_i915_gem_object *pinned;
        struct i915_sw_dma_fence_cb cb;
@@ -302,13 +304,10 @@ static int __vma_bind(struct dma_fence_work *work)
 {
        struct i915_vma_work *vw = container_of(work, typeof(*vw), base);
        struct i915_vma *vma = vw->vma;
-       int err;
-
-       err = vma->ops->bind_vma(vma->vm, vma, vw->cache_level, vw->flags);
-       if (err)
-               atomic_or(I915_VMA_ERROR, &vma->flags);
 
-       return err;
+       vma->ops->bind_vma(vw->vm, &vw->stash,
+                          vma, vw->cache_level, vw->flags);
+       return 0;
 }
 
 static void __vma_release(struct dma_fence_work *work)
@@ -317,6 +316,9 @@ static void __vma_release(struct dma_fence_work *work)
 
        if (vw->pinned)
                __i915_gem_object_unpin_pages(vw->pinned);
+
+       i915_vm_free_pt_stash(vw->vm, &vw->stash);
+       i915_vm_put(vw->vm);
 }
 
 static const struct dma_fence_work_ops bind_ops = {
@@ -376,7 +378,6 @@ int i915_vma_bind(struct i915_vma *vma,
 {
        u32 bind_flags;
        u32 vma_flags;
-       int ret;
 
        GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
        GEM_BUG_ON(vma->size > vma->node.size);
@@ -433,9 +434,7 @@ int i915_vma_bind(struct i915_vma *vma,
                        work->pinned = vma->obj;
                }
        } else {
-               ret = vma->ops->bind_vma(vma->vm, vma, cache_level, bind_flags);
-               if (ret)
-                       return ret;
+               vma->ops->bind_vma(vma->vm, NULL, vma, cache_level, bind_flags);
        }
 
        atomic_or(bind_flags, &vma->flags);
@@ -853,13 +852,19 @@ static void vma_unbind_pages(struct i915_vma *vma)
        __vma_put_pages(vma, count | count << I915_VMA_PAGES_BIAS);
 }
 
-int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+                   u64 size, u64 alignment, u64 flags)
 {
        struct i915_vma_work *work = NULL;
        intel_wakeref_t wakeref = 0;
        unsigned int bound;
        int err;
 
+#ifdef CONFIG_PROVE_LOCKING
+       if (debug_locks && lockdep_is_held(&vma->vm->i915->drm.struct_mutex))
+               WARN_ON(!ww);
+#endif
+
        BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
        BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
 
@@ -873,16 +878,32 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
        if (err)
                return err;
 
+       if (flags & PIN_GLOBAL)
+               wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm);
+
        if (flags & vma->vm->bind_async_flags) {
                work = i915_vma_work();
                if (!work) {
                        err = -ENOMEM;
-                       goto err_pages;
+                       goto err_rpm;
                }
-       }
 
-       if (flags & PIN_GLOBAL)
-               wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm);
+               work->vm = i915_vm_get(vma->vm);
+
+               /* Allocate enough page directories to used PTE */
+               if (vma->vm->allocate_va_range) {
+                       err = i915_vm_alloc_pt_stash(vma->vm,
+                                                    &work->stash,
+                                                    vma->size);
+                       if (err)
+                               goto err_fence;
+
+                       err = i915_vm_pin_pt_stash(vma->vm,
+                                                  &work->stash);
+                       if (err)
+                               goto err_fence;
+               }
+       }
 
        /*
         * Differentiate between user/kernel vma inside the aliasing-ppgtt.
@@ -971,9 +992,9 @@ err_unlock:
 err_fence:
        if (work)
                dma_fence_work_commit_imm(&work->base);
+err_rpm:
        if (wakeref)
                intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref);
-err_pages:
        vma_put_pages(vma);
        return err;
 }
@@ -989,7 +1010,8 @@ static void flush_idle_contexts(struct intel_gt *gt)
        intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT);
 }
 
-int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags)
+int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+                 u32 align, unsigned int flags)
 {
        struct i915_address_space *vm = vma->vm;
        int err;
@@ -997,7 +1019,7 @@ int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags)
        GEM_BUG_ON(!i915_vma_is_ggtt(vma));
 
        do {
-               err = i915_vma_pin(vma, 0, align, flags | PIN_GLOBAL);
+               err = i915_vma_pin_ww(vma, ww, 0, align, flags | PIN_GLOBAL);
                if (err != -ENOSPC) {
                        if (!err) {
                                err = i915_vma_wait_for_bind(vma);
@@ -1167,6 +1189,12 @@ void i915_vma_revoke_mmap(struct i915_vma *vma)
                list_del(&vma->obj->userfault_link);
 }
 
+static int
+__i915_request_await_bind(struct i915_request *rq, struct i915_vma *vma)
+{
+       return __i915_request_await_exclusive(rq, &vma->active);
+}
+
 int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq)
 {
        int err;
@@ -1174,8 +1202,7 @@ int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq)
        GEM_BUG_ON(!i915_vma_is_pinned(vma));
 
        /* Wait for the vma to be bound before we start! */
-       err = i915_request_await_active(rq, &vma->active,
-                                       I915_ACTIVE_AWAIT_EXCL);
+       err = __i915_request_await_bind(rq, vma);
        if (err)
                return err;