drm/i915: Leave the aliasing-ppgtt size alone
[linux-2.6-block.git] / drivers / gpu / drm / i915 / i915_gem_gtt.c
index b1a7a8b9b46aa3ea8dcfb84d5af39ba8fa902bfb..6239a9adbf14e4cf0e1973039d58303af1737101 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "display/intel_frontbuffer.h"
 #include "gt/intel_gt.h"
+#include "gt/intel_gt_requests.h"
 
 #include "i915_drv.h"
 #include "i915_scatterlist.h"
@@ -132,9 +133,15 @@ static void gen6_ggtt_invalidate(struct i915_ggtt *ggtt)
 static void guc_ggtt_invalidate(struct i915_ggtt *ggtt)
 {
        struct intel_uncore *uncore = ggtt->vm.gt->uncore;
+       struct drm_i915_private *i915 = ggtt->vm.i915;
 
        gen6_ggtt_invalidate(ggtt);
-       intel_uncore_write_fw(uncore, GEN8_GTCR, GEN8_GTCR_INVALIDATE);
+
+       if (INTEL_GEN(i915) >= 12)
+               intel_uncore_write_fw(uncore, GEN12_GUC_TLB_INV_CR,
+                                     GEN12_GUC_TLB_INV_CR_INVALIDATE);
+       else
+               intel_uncore_write_fw(uncore, GEN8_GTCR, GEN8_GTCR_INVALIDATE);
 }
 
 static void gmch_ggtt_invalidate(struct i915_ggtt *ggtt)
@@ -144,16 +151,18 @@ static void gmch_ggtt_invalidate(struct i915_ggtt *ggtt)
 
 static int ppgtt_bind_vma(struct i915_vma *vma,
                          enum i915_cache_level cache_level,
-                         u32 unused)
+                         u32 flags)
 {
        u32 pte_flags;
        int err;
 
-       if (!(vma->flags & I915_VMA_LOCAL_BIND)) {
+       if (flags & I915_VMA_ALLOC) {
                err = vma->vm->allocate_va_range(vma->vm,
                                                 vma->node.start, vma->size);
                if (err)
                        return err;
+
+               set_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma));
        }
 
        /* Applicable to VLV, and gen8+ */
@@ -161,14 +170,17 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
        if (i915_gem_object_is_readonly(vma->obj))
                pte_flags |= PTE_READ_ONLY;
 
+       GEM_BUG_ON(!test_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma)));
        vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
+       wmb();
 
        return 0;
 }
 
 static void ppgtt_unbind_vma(struct i915_vma *vma)
 {
-       vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
+       if (test_and_clear_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma)))
+               vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
 }
 
 static int ppgtt_set_pages(struct i915_vma *vma)
@@ -496,22 +508,26 @@ static void i915_address_space_fini(struct i915_address_space *vm)
        mutex_destroy(&vm->mutex);
 }
 
-static void ppgtt_destroy_vma(struct i915_address_space *vm)
+void __i915_vm_close(struct i915_address_space *vm)
 {
-       struct list_head *phases[] = {
-               &vm->bound_list,
-               &vm->unbound_list,
-               NULL,
-       }, **phase;
+       struct i915_vma *vma, *vn;
+
+       mutex_lock(&vm->mutex);
+       list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) {
+               struct drm_i915_gem_object *obj = vma->obj;
 
-       mutex_lock(&vm->i915->drm.struct_mutex);
-       for (phase = phases; *phase; phase++) {
-               struct i915_vma *vma, *vn;
+               /* Keep the obj (and hence the vma) alive as _we_ destroy it */
+               if (!kref_get_unless_zero(&obj->base.refcount))
+                       continue;
+
+               atomic_and(~I915_VMA_PIN_MASK, &vma->flags);
+               WARN_ON(__i915_vma_unbind(vma));
+               i915_vma_destroy(vma);
 
-               list_for_each_entry_safe(vma, vn, *phase, vm_link)
-                       i915_vma_destroy(vma);
+               i915_gem_object_put(obj);
        }
-       mutex_unlock(&vm->i915->drm.struct_mutex);
+       GEM_BUG_ON(!list_empty(&vm->bound_list));
+       mutex_unlock(&vm->mutex);
 }
 
 static void __i915_vm_release(struct work_struct *work)
@@ -519,11 +535,6 @@ static void __i915_vm_release(struct work_struct *work)
        struct i915_address_space *vm =
                container_of(work, struct i915_address_space, rcu.work);
 
-       ppgtt_destroy_vma(vm);
-
-       GEM_BUG_ON(!list_empty(&vm->bound_list));
-       GEM_BUG_ON(!list_empty(&vm->unbound_list));
-
        vm->cleanup(vm);
        i915_address_space_fini(vm);
 
@@ -538,7 +549,6 @@ void i915_vm_release(struct kref *kref)
        GEM_BUG_ON(i915_is_ggtt(vm));
        trace_i915_ppgtt_release(vm);
 
-       vm->closed = true;
        queue_rcu_work(vm->i915->wq, &vm->rcu);
 }
 
@@ -546,6 +556,7 @@ static void i915_address_space_init(struct i915_address_space *vm, int subclass)
 {
        kref_init(&vm->ref);
        INIT_RCU_WORK(&vm->rcu, __i915_vm_release);
+       atomic_set(&vm->open, 1);
 
        /*
         * The vm->mutex must be reclaim safe (for use in the shrinker).
@@ -562,7 +573,6 @@ static void i915_address_space_init(struct i915_address_space *vm, int subclass)
 
        stash_init(&vm->free_pages);
 
-       INIT_LIST_HEAD(&vm->unbound_list);
        INIT_LIST_HEAD(&vm->bound_list);
 }
 
@@ -816,17 +826,6 @@ release_pd_entry(struct i915_page_directory * const pd,
        return free;
 }
 
-/*
- * PDE TLBs are a pain to invalidate on GEN8+. When we modify
- * the page table structures, we mark them dirty so that
- * context switching/execlist queuing code takes extra steps
- * to ensure that tlbs are flushed.
- */
-static void mark_tlbs_dirty(struct i915_ppgtt *ppgtt)
-{
-       ppgtt->pd_dirty_engines = ALL_ENGINES;
-}
-
 static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
 {
        struct drm_i915_private *dev_priv = ppgtt->vm.i915;
@@ -1367,7 +1366,9 @@ static int gen8_init_scratch(struct i915_address_space *vm)
        if (vm->has_read_only &&
            vm->i915->kernel_context &&
            vm->i915->kernel_context->vm) {
-               struct i915_address_space *clone = vm->i915->kernel_context->vm;
+               struct i915_address_space *clone =
+                       rcu_dereference_protected(vm->i915->kernel_context->vm,
+                                                 true); /* static */
 
                GEM_BUG_ON(!clone->has_read_only);
 
@@ -1422,6 +1423,7 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
                set_pd_entry(pd, idx, pde);
                atomic_inc(px_used(pde)); /* keep pinned */
        }
+       wmb();
 
        return 0;
 }
@@ -1489,8 +1491,10 @@ static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
         *
         * Gen11 has HSDES#:1807136187 unresolved. Disable ro support
         * for now.
+        *
+        * Gen12 has inherited the same read-only fault issue from gen11.
         */
-       ppgtt->vm.has_read_only = INTEL_GEN(i915) != 11;
+       ppgtt->vm.has_read_only = !IS_GEN_RANGE(i915, 11, 12);
 
        /* There are only few exceptions for gen >=6. chv and bxt.
         * And we are not sure about the latter so play safe for now.
@@ -1509,13 +1513,12 @@ static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
        }
 
        if (!i915_vm_is_4lvl(&ppgtt->vm)) {
-               if (intel_vgpu_active(i915)) {
-                       err = gen8_preallocate_top_level_pdp(ppgtt);
-                       if (err)
-                               goto err_free_pd;
-               }
+               err = gen8_preallocate_top_level_pdp(ppgtt);
+               if (err)
+                       goto err_free_pd;
        }
 
+       ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
        ppgtt->vm.insert_entries = gen8_ppgtt_insert;
        ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
        ppgtt->vm.clear_range = gen8_ppgtt_clear;
@@ -1566,7 +1569,7 @@ static void gen7_ppgtt_enable(struct intel_gt *gt)
        }
        intel_uncore_write(uncore, GAM_ECOCHK, ecochk);
 
-       for_each_engine(engine, i915, id) {
+       for_each_engine(engine, gt, id) {
                /* GFX_MODE is per-ring on gen7+ */
                ENGINE_WRITE(engine,
                             RING_MODE_GEN7,
@@ -1729,10 +1732,8 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
        }
        spin_unlock(&pd->lock);
 
-       if (flush) {
-               mark_tlbs_dirty(&ppgtt->base);
+       if (flush)
                gen6_ggtt_invalidate(vm->gt->ggtt);
-       }
 
        goto out;
 
@@ -1786,15 +1787,13 @@ static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt)
 static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 {
        struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm));
-       struct drm_i915_private *i915 = vm->i915;
 
-       /* FIXME remove the struct_mutex to bring the locking under control */
-       mutex_lock(&i915->drm.struct_mutex);
        i915_vma_destroy(ppgtt->vma);
-       mutex_unlock(&i915->drm.struct_mutex);
 
        gen6_ppgtt_free_pd(ppgtt);
        free_scratch(vm);
+
+       mutex_destroy(&ppgtt->pin_mutex);
        kfree(ppgtt->base.pd);
 }
 
@@ -1827,7 +1826,6 @@ static int pd_vma_bind(struct i915_vma *vma,
        gen6_for_all_pdes(pt, ppgtt->base.pd, pde)
                gen6_write_pde(ppgtt, pde, pt);
 
-       mark_tlbs_dirty(&ppgtt->base);
        gen6_ggtt_invalidate(ggtt);
 
        return 0;
@@ -1866,7 +1864,6 @@ static const struct i915_vma_ops pd_vma_ops = {
 
 static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size)
 {
-       struct drm_i915_private *i915 = ppgtt->base.vm.i915;
        struct i915_ggtt *ggtt = ppgtt->base.vm.gt->ggtt;
        struct i915_vma *vma;
 
@@ -1877,33 +1874,30 @@ static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size)
        if (!vma)
                return ERR_PTR(-ENOMEM);
 
-       i915_active_init(i915, &vma->active, NULL, NULL);
+       i915_active_init(&vma->active, NULL, NULL);
 
-       vma->vm = &ggtt->vm;
+       mutex_init(&vma->pages_mutex);
+       vma->vm = i915_vm_get(&ggtt->vm);
        vma->ops = &pd_vma_ops;
        vma->private = ppgtt;
 
        vma->size = size;
        vma->fence_size = size;
-       vma->flags = I915_VMA_GGTT;
+       atomic_set(&vma->flags, I915_VMA_GGTT);
        vma->ggtt_view.type = I915_GGTT_VIEW_ROTATED; /* prevent fencing */
 
        INIT_LIST_HEAD(&vma->obj_link);
        INIT_LIST_HEAD(&vma->closed_link);
 
-       mutex_lock(&vma->vm->mutex);
-       list_add(&vma->vm_link, &vma->vm->unbound_list);
-       mutex_unlock(&vma->vm->mutex);
-
        return vma;
 }
 
 int gen6_ppgtt_pin(struct i915_ppgtt *base)
 {
        struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base);
-       int err;
+       int err = 0;
 
-       GEM_BUG_ON(ppgtt->base.vm.closed);
+       GEM_BUG_ON(!atomic_read(&ppgtt->base.vm.open));
 
        /*
         * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
@@ -1911,24 +1905,26 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base)
         * (When vma->pin_count becomes atomic, I expect we will naturally
         * need a larger, unpacked, type and kill this redundancy.)
         */
-       if (ppgtt->pin_count++)
+       if (atomic_add_unless(&ppgtt->pin_count, 1, 0))
                return 0;
 
+       if (mutex_lock_interruptible(&ppgtt->pin_mutex))
+               return -EINTR;
+
        /*
         * PPGTT PDEs reside in the GGTT and consists of 512 entries. The
         * allocator works in address space sizes, so it's multiplied by page
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
-       err = i915_vma_pin(ppgtt->vma,
-                          0, GEN6_PD_ALIGN,
-                          PIN_GLOBAL | PIN_HIGH);
-       if (err)
-               goto unpin;
-
-       return 0;
+       if (!atomic_read(&ppgtt->pin_count)) {
+               err = i915_vma_pin(ppgtt->vma,
+                                  0, GEN6_PD_ALIGN,
+                                  PIN_GLOBAL | PIN_HIGH);
+       }
+       if (!err)
+               atomic_inc(&ppgtt->pin_count);
+       mutex_unlock(&ppgtt->pin_mutex);
 
-unpin:
-       ppgtt->pin_count = 0;
        return err;
 }
 
@@ -1936,22 +1932,20 @@ void gen6_ppgtt_unpin(struct i915_ppgtt *base)
 {
        struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base);
 
-       GEM_BUG_ON(!ppgtt->pin_count);
-       if (--ppgtt->pin_count)
-               return;
-
-       i915_vma_unpin(ppgtt->vma);
+       GEM_BUG_ON(!atomic_read(&ppgtt->pin_count));
+       if (atomic_dec_and_test(&ppgtt->pin_count))
+               i915_vma_unpin(ppgtt->vma);
 }
 
 void gen6_ppgtt_unpin_all(struct i915_ppgtt *base)
 {
        struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base);
 
-       if (!ppgtt->pin_count)
+       if (!atomic_read(&ppgtt->pin_count))
                return;
 
-       ppgtt->pin_count = 0;
        i915_vma_unpin(ppgtt->vma);
+       atomic_set(&ppgtt->pin_count, 0);
 }
 
 static struct i915_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
@@ -1964,9 +1958,12 @@ static struct i915_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
        if (!ppgtt)
                return ERR_PTR(-ENOMEM);
 
+       mutex_init(&ppgtt->pin_mutex);
+
        ppgtt_init(&ppgtt->base, &i915->gt);
        ppgtt->base.vm.top = 1;
 
+       ppgtt->base.vm.bind_async_flags = I915_VMA_LOCAL_BIND;
        ppgtt->base.vm.allocate_va_range = gen6_alloc_va_range;
        ppgtt->base.vm.clear_range = gen6_ppgtt_clear_range;
        ppgtt->base.vm.insert_entries = gen6_ppgtt_insert_entries;
@@ -2023,7 +2020,7 @@ static void gtt_write_workarounds(struct intel_gt *gt)
                intel_uncore_write(uncore,
                                   GEN8_L3_LRA_1_GPGPU,
                                   GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
-       else if (INTEL_GEN(i915) >= 9)
+       else if (INTEL_GEN(i915) >= 9 && INTEL_GEN(i915) <= 11)
                intel_uncore_write(uncore,
                                   GEN8_L3_LRA_1_GPGPU,
                                   GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
@@ -2202,7 +2199,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
 
        gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm;
        gtt_entries += vma->node.start / I915_GTT_PAGE_SIZE;
-       for_each_sgt_dma(addr, sgt_iter, vma->pages)
+       for_each_sgt_daddr(addr, sgt_iter, vma->pages)
                gen8_set_pte(gtt_entries++, pte_encode | addr);
 
        /*
@@ -2243,7 +2240,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
        unsigned int i = vma->node.start / I915_GTT_PAGE_SIZE;
        struct sgt_iter iter;
        dma_addr_t addr;
-       for_each_sgt_dma(addr, iter, vma->pages)
+       for_each_sgt_daddr(addr, iter, vma->pages)
                iowrite32(vm->pte_encode(addr, level, flags), &entries[i++]);
 
        /*
@@ -2448,7 +2445,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
         * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
         * upgrade to both bound if we bind either to avoid double-binding.
         */
-       vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
+       atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
 
        return 0;
 }
@@ -2478,14 +2475,18 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
        if (flags & I915_VMA_LOCAL_BIND) {
                struct i915_ppgtt *alias = i915_vm_to_ggtt(vma->vm)->alias;
 
-               if (!(vma->flags & I915_VMA_LOCAL_BIND)) {
+               if (flags & I915_VMA_ALLOC) {
                        ret = alias->vm.allocate_va_range(&alias->vm,
                                                          vma->node.start,
                                                          vma->size);
                        if (ret)
                                return ret;
+
+                       set_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma));
                }
 
+               GEM_BUG_ON(!test_bit(I915_VMA_ALLOC_BIT,
+                                    __i915_vma_flags(vma)));
                alias->vm.insert_entries(&alias->vm, vma,
                                         cache_level, pte_flags);
        }
@@ -2506,7 +2507,7 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
 {
        struct drm_i915_private *i915 = vma->vm->i915;
 
-       if (vma->flags & I915_VMA_GLOBAL_BIND) {
+       if (i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND)) {
                struct i915_address_space *vm = vma->vm;
                intel_wakeref_t wakeref;
 
@@ -2514,7 +2515,7 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
                        vm->clear_range(vm, vma->node.start, vma->size);
        }
 
-       if (vma->flags & I915_VMA_LOCAL_BIND) {
+       if (test_and_clear_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma))) {
                struct i915_address_space *vm =
                        &i915_vm_to_ggtt(vma->vm)->alias->vm;
 
@@ -2530,7 +2531,9 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
        struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
        if (unlikely(ggtt->do_idle_maps)) {
-               if (i915_gem_wait_for_idle(dev_priv, 0, MAX_SCHEDULE_TIMEOUT)) {
+               /* XXX This does not prevent more requests being submitted! */
+               if (intel_gt_retire_requests_timeout(ggtt->vm.gt,
+                                                    -MAX_SCHEDULE_TIMEOUT)) {
                        DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");
                        /* Wait a bit, in hopes it avoids the hang */
                        udelay(10);
@@ -2555,12 +2558,12 @@ static int ggtt_set_pages(struct i915_vma *vma)
        return 0;
 }
 
-static void i915_gtt_color_adjust(const struct drm_mm_node *node,
-                                 unsigned long color,
-                                 u64 *start,
-                                 u64 *end)
+static void i915_ggtt_color_adjust(const struct drm_mm_node *node,
+                                  unsigned long color,
+                                  u64 *start,
+                                  u64 *end)
 {
-       if (node->allocated && node->color != color)
+       if (i915_node_color_differs(node, color))
                *start += I915_GTT_PAGE_SIZE;
 
        /* Also leave a space between the unallocated reserved node after the
@@ -2598,6 +2601,7 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt)
                goto err_ppgtt;
 
        ggtt->alias = ppgtt;
+       ggtt->vm.bind_async_flags |= ppgtt->vm.bind_async_flags;
 
        GEM_BUG_ON(ggtt->vm.vma_ops.bind_vma != ggtt_bind_vma);
        ggtt->vm.vma_ops.bind_vma = aliasing_gtt_bind_vma;
@@ -2614,22 +2618,16 @@ err_ppgtt:
 
 static void fini_aliasing_ppgtt(struct i915_ggtt *ggtt)
 {
-       struct drm_i915_private *i915 = ggtt->vm.i915;
        struct i915_ppgtt *ppgtt;
 
-       mutex_lock(&i915->drm.struct_mutex);
-
        ppgtt = fetch_and_zero(&ggtt->alias);
        if (!ppgtt)
-               goto out;
+               return;
 
        i915_vm_put(&ppgtt->vm);
 
        ggtt->vm.vma_ops.bind_vma   = ggtt_bind_vma;
        ggtt->vm.vma_ops.unbind_vma = ggtt_unbind_vma;
-
-out:
-       mutex_unlock(&i915->drm.struct_mutex);
 }
 
 static int ggtt_reserve_guc_top(struct i915_ggtt *ggtt)
@@ -2661,7 +2659,8 @@ static void ggtt_release_guc_top(struct i915_ggtt *ggtt)
 static void cleanup_init_ggtt(struct i915_ggtt *ggtt)
 {
        ggtt_release_guc_top(ggtt);
-       drm_mm_remove_node(&ggtt->error_capture);
+       if (drm_mm_node_allocated(&ggtt->error_capture))
+               drm_mm_remove_node(&ggtt->error_capture);
 }
 
 static int init_ggtt(struct i915_ggtt *ggtt)
@@ -2692,13 +2691,15 @@ static int init_ggtt(struct i915_ggtt *ggtt)
        if (ret)
                return ret;
 
-       /* Reserve a mappable slot for our lockless error capture */
-       ret = drm_mm_insert_node_in_range(&ggtt->vm.mm, &ggtt->error_capture,
-                                         PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE,
-                                         0, ggtt->mappable_end,
-                                         DRM_MM_INSERT_LOW);
-       if (ret)
-               return ret;
+       if (ggtt->mappable_end) {
+               /* Reserve a mappable slot for our lockless error capture */
+               ret = drm_mm_insert_node_in_range(&ggtt->vm.mm, &ggtt->error_capture,
+                                                 PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE,
+                                                 0, ggtt->mappable_end,
+                                                 DRM_MM_INSERT_LOW);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * The upper portion of the GuC address space has a sizeable hole
@@ -2746,35 +2747,33 @@ int i915_init_ggtt(struct drm_i915_private *i915)
 
 static void ggtt_cleanup_hw(struct i915_ggtt *ggtt)
 {
-       struct drm_i915_private *i915 = ggtt->vm.i915;
        struct i915_vma *vma, *vn;
 
-       ggtt->vm.closed = true;
+       atomic_set(&ggtt->vm.open, 0);
 
        rcu_barrier(); /* flush the RCU'ed__i915_vm_release */
-       flush_workqueue(i915->wq);
+       flush_workqueue(ggtt->vm.i915->wq);
 
-       mutex_lock(&i915->drm.struct_mutex);
+       mutex_lock(&ggtt->vm.mutex);
 
        list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link)
-               WARN_ON(i915_vma_unbind(vma));
+               WARN_ON(__i915_vma_unbind(vma));
 
        if (drm_mm_node_allocated(&ggtt->error_capture))
                drm_mm_remove_node(&ggtt->error_capture);
 
        ggtt_release_guc_top(ggtt);
-
-       if (drm_mm_initialized(&ggtt->vm.mm)) {
-               intel_vgt_deballoon(ggtt);
-               i915_address_space_fini(&ggtt->vm);
-       }
+       intel_vgt_deballoon(ggtt);
 
        ggtt->vm.cleanup(&ggtt->vm);
 
-       mutex_unlock(&i915->drm.struct_mutex);
+       mutex_unlock(&ggtt->vm.mutex);
+       i915_address_space_fini(&ggtt->vm);
 
        arch_phys_wc_del(ggtt->mtrr);
-       io_mapping_fini(&ggtt->iomap);
+
+       if (ggtt->iomap.size)
+               io_mapping_fini(&ggtt->iomap);
 }
 
 /**
@@ -2794,8 +2793,6 @@ void i915_ggtt_driver_release(struct drm_i915_private *i915)
                set_pages_array_wb(pvec->pages, pvec->nr);
                __pagevec_release(pvec);
        }
-
-       i915_gem_cleanup_stolen(i915);
 }
 
 static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
@@ -2873,35 +2870,51 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
        return 0;
 }
 
-static void tgl_setup_private_ppat(struct drm_i915_private *dev_priv)
+static void tgl_setup_private_ppat(struct intel_uncore *uncore)
 {
        /* TGL doesn't support LLC or AGE settings */
-       I915_WRITE(GEN12_PAT_INDEX(0), GEN8_PPAT_WB);
-       I915_WRITE(GEN12_PAT_INDEX(1), GEN8_PPAT_WC);
-       I915_WRITE(GEN12_PAT_INDEX(2), GEN8_PPAT_WT);
-       I915_WRITE(GEN12_PAT_INDEX(3), GEN8_PPAT_UC);
-       I915_WRITE(GEN12_PAT_INDEX(4), GEN8_PPAT_WB);
-       I915_WRITE(GEN12_PAT_INDEX(5), GEN8_PPAT_WB);
-       I915_WRITE(GEN12_PAT_INDEX(6), GEN8_PPAT_WB);
-       I915_WRITE(GEN12_PAT_INDEX(7), GEN8_PPAT_WB);
-}
-
-static void cnl_setup_private_ppat(struct drm_i915_private *dev_priv)
-{
-       I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_WB | GEN8_PPAT_LLC);
-       I915_WRITE(GEN10_PAT_INDEX(1), GEN8_PPAT_WC | GEN8_PPAT_LLCELLC);
-       I915_WRITE(GEN10_PAT_INDEX(2), GEN8_PPAT_WT | GEN8_PPAT_LLCELLC);
-       I915_WRITE(GEN10_PAT_INDEX(3), GEN8_PPAT_UC);
-       I915_WRITE(GEN10_PAT_INDEX(4), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0));
-       I915_WRITE(GEN10_PAT_INDEX(5), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1));
-       I915_WRITE(GEN10_PAT_INDEX(6), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2));
-       I915_WRITE(GEN10_PAT_INDEX(7), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(0), GEN8_PPAT_WB);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(1), GEN8_PPAT_WC);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(2), GEN8_PPAT_WT);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(3), GEN8_PPAT_UC);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(4), GEN8_PPAT_WB);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(5), GEN8_PPAT_WB);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(6), GEN8_PPAT_WB);
+       intel_uncore_write(uncore, GEN12_PAT_INDEX(7), GEN8_PPAT_WB);
+}
+
+static void cnl_setup_private_ppat(struct intel_uncore *uncore)
+{
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(0),
+                          GEN8_PPAT_WB | GEN8_PPAT_LLC);
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(1),
+                          GEN8_PPAT_WC | GEN8_PPAT_LLCELLC);
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(2),
+                          GEN8_PPAT_WT | GEN8_PPAT_LLCELLC);
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(3),
+                          GEN8_PPAT_UC);
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(4),
+                          GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0));
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(5),
+                          GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1));
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(6),
+                          GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2));
+       intel_uncore_write(uncore,
+                          GEN10_PAT_INDEX(7),
+                          GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
 }
 
 /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability
  * bits. When using advanced contexts each context stores its own PAT, but
  * writing this data shouldn't be harmful even in those cases. */
-static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
+static void bdw_setup_private_ppat(struct intel_uncore *uncore)
 {
        u64 pat;
 
@@ -2914,11 +2927,11 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
              GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
              GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
 
-       I915_WRITE(GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
-       I915_WRITE(GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
+       intel_uncore_write(uncore, GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
+       intel_uncore_write(uncore, GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
 }
 
-static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
+static void chv_setup_private_ppat(struct intel_uncore *uncore)
 {
        u64 pat;
 
@@ -2950,8 +2963,8 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
              GEN8_PPAT(6, CHV_PPAT_SNOOP) |
              GEN8_PPAT(7, CHV_PPAT_SNOOP);
 
-       I915_WRITE(GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
-       I915_WRITE(GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
+       intel_uncore_write(uncore, GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
+       intel_uncore_write(uncore, GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
 }
 
 static void gen6_gmch_remove(struct i915_address_space *vm)
@@ -2962,18 +2975,26 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
        cleanup_scratch_page(vm);
 }
 
-static void setup_private_pat(struct drm_i915_private *dev_priv)
+static void setup_private_pat(struct intel_uncore *uncore)
 {
-       GEM_BUG_ON(INTEL_GEN(dev_priv) < 8);
+       struct drm_i915_private *i915 = uncore->i915;
 
-       if (INTEL_GEN(dev_priv) >= 12)
-               tgl_setup_private_ppat(dev_priv);
-       else if (INTEL_GEN(dev_priv) >= 10)
-               cnl_setup_private_ppat(dev_priv);
-       else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv))
-               chv_setup_private_ppat(dev_priv);
+       GEM_BUG_ON(INTEL_GEN(i915) < 8);
+
+       if (INTEL_GEN(i915) >= 12)
+               tgl_setup_private_ppat(uncore);
+       else if (INTEL_GEN(i915) >= 10)
+               cnl_setup_private_ppat(uncore);
+       else if (IS_CHERRYVIEW(i915) || IS_GEN9_LP(i915))
+               chv_setup_private_ppat(uncore);
        else
-               bdw_setup_private_ppat(dev_priv);
+               bdw_setup_private_ppat(uncore);
+}
+
+static struct resource pci_resource(struct pci_dev *pdev, int bar)
+{
+       return (struct resource)DEFINE_RES_MEM(pci_resource_start(pdev, bar),
+                                              pci_resource_len(pdev, bar));
 }
 
 static int gen8_gmch_probe(struct i915_ggtt *ggtt)
@@ -2985,10 +3006,10 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
        int err;
 
        /* TODO: We're not aware of mappable constraints on gen8 yet */
-       ggtt->gmadr =
-               (struct resource) DEFINE_RES_MEM(pci_resource_start(pdev, 2),
-                                                pci_resource_len(pdev, 2));
-       ggtt->mappable_end = resource_size(&ggtt->gmadr);
+       if (!IS_DGFX(dev_priv)) {
+               ggtt->gmadr = pci_resource(pdev, 2);
+               ggtt->mappable_end = resource_size(&ggtt->gmadr);
+       }
 
        err = pci_set_dma_mask(pdev, DMA_BIT_MASK(39));
        if (!err)
@@ -3029,7 +3050,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 
        ggtt->vm.pte_encode = gen8_pte_encode;
 
-       setup_private_pat(dev_priv);
+       setup_private_pat(ggtt->vm.gt->uncore);
 
        return ggtt_probe_common(ggtt, size);
 }
@@ -3200,9 +3221,6 @@ int i915_ggtt_probe_hw(struct drm_i915_private *i915)
 static int ggtt_init_hw(struct i915_ggtt *ggtt)
 {
        struct drm_i915_private *i915 = ggtt->vm.i915;
-       int ret = 0;
-
-       mutex_lock(&i915->drm.struct_mutex);
 
        i915_address_space_init(&ggtt->vm, VM_CLASS_GGTT);
 
@@ -3212,24 +3230,23 @@ static int ggtt_init_hw(struct i915_ggtt *ggtt)
        ggtt->vm.has_read_only = IS_VALLEYVIEW(i915);
 
        if (!HAS_LLC(i915) && !HAS_PPGTT(i915))
-               ggtt->vm.mm.color_adjust = i915_gtt_color_adjust;
-
-       if (!io_mapping_init_wc(&ggtt->iomap,
-                               ggtt->gmadr.start,
-                               ggtt->mappable_end)) {
-               ggtt->vm.cleanup(&ggtt->vm);
-               ret = -EIO;
-               goto out;
-       }
+               ggtt->vm.mm.color_adjust = i915_ggtt_color_adjust;
+
+       if (ggtt->mappable_end) {
+               if (!io_mapping_init_wc(&ggtt->iomap,
+                                       ggtt->gmadr.start,
+                                       ggtt->mappable_end)) {
+                       ggtt->vm.cleanup(&ggtt->vm);
+                       return -EIO;
+               }
 
-       ggtt->mtrr = arch_phys_wc_add(ggtt->gmadr.start, ggtt->mappable_end);
+               ggtt->mtrr = arch_phys_wc_add(ggtt->gmadr.start,
+                                             ggtt->mappable_end);
+       }
 
        i915_ggtt_init_fences(ggtt);
 
-out:
-       mutex_unlock(&i915->drm.struct_mutex);
-
-       return ret;
+       return 0;
 }
 
 /**
@@ -3251,19 +3268,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
        if (ret)
                return ret;
 
-       /*
-        * Initialise stolen early so that we may reserve preallocated
-        * objects for the BIOS to KMS transition.
-        */
-       ret = i915_gem_init_stolen(dev_priv);
-       if (ret)
-               goto out_gtt_cleanup;
-
        return 0;
-
-out_gtt_cleanup:
-       dev_priv->ggtt.vm.cleanup(&dev_priv->ggtt.vm);
-       return ret;
 }
 
 int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
@@ -3301,6 +3306,7 @@ static void ggtt_restore_mappings(struct i915_ggtt *ggtt)
 {
        struct i915_vma *vma, *vn;
        bool flush = false;
+       int open;
 
        intel_gt_check_and_clear_faults(ggtt->vm.gt);
 
@@ -3308,33 +3314,31 @@ static void ggtt_restore_mappings(struct i915_ggtt *ggtt)
 
        /* First fill our portion of the GTT with scratch pages */
        ggtt->vm.clear_range(&ggtt->vm, 0, ggtt->vm.total);
-       ggtt->vm.closed = true; /* skip rewriting PTE on VMA unbind */
+
+       /* Skip rewriting PTE on VMA unbind. */
+       open = atomic_xchg(&ggtt->vm.open, 0);
 
        /* clflush objects bound into the GGTT and rebind them. */
        list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link) {
                struct drm_i915_gem_object *obj = vma->obj;
 
-               if (!(vma->flags & I915_VMA_GLOBAL_BIND))
+               if (!i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
                        continue;
 
-               mutex_unlock(&ggtt->vm.mutex);
-
-               if (!i915_vma_unbind(vma))
-                       goto lock;
+               if (!__i915_vma_unbind(vma))
+                       continue;
 
+               clear_bit(I915_VMA_GLOBAL_BIND_BIT, __i915_vma_flags(vma));
                WARN_ON(i915_vma_bind(vma,
                                      obj ? obj->cache_level : 0,
-                                     PIN_UPDATE));
+                                     PIN_GLOBAL, NULL));
                if (obj) { /* only used during resume => exclusive access */
                        flush |= fetch_and_zero(&obj->write_domain);
                        obj->read_domains |= I915_GEM_DOMAIN_GTT;
                }
-
-lock:
-               mutex_lock(&ggtt->vm.mutex);
        }
 
-       ggtt->vm.closed = false;
+       atomic_set(&ggtt->vm.open, open);
        ggtt->invalidate(ggtt);
 
        mutex_unlock(&ggtt->vm.mutex);
@@ -3345,10 +3349,12 @@ lock:
 
 void i915_gem_restore_gtt_mappings(struct drm_i915_private *i915)
 {
-       ggtt_restore_mappings(&i915->ggtt);
+       struct i915_ggtt *ggtt = &i915->ggtt;
+
+       ggtt_restore_mappings(ggtt);
 
        if (INTEL_GEN(i915) >= 8)
-               setup_private_pat(i915);
+               setup_private_pat(ggtt->vm.gt->uncore);
 }
 
 static struct scatterlist *
@@ -3726,7 +3732,8 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,
        u64 offset;
        int err;
 
-       lockdep_assert_held(&vm->i915->drm.struct_mutex);
+       lockdep_assert_held(&vm->mutex);
+
        GEM_BUG_ON(!size);
        GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE));
        GEM_BUG_ON(alignment && !is_power_of_2(alignment));