These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / mmu / nv50.c
index b83550f..a1f8d65 100644 (file)
  *
  * Authors: Ben Skeggs
  */
-#include <subdev/mmu.h>
-#include <subdev/bar.h>
-#include <subdev/fb.h>
-#include <subdev/timer.h>
+#include "priv.h"
 
-#include <core/engine.h>
 #include <core/gpuobj.h>
-
-struct nv50_mmu_priv {
-       struct nvkm_mmu base;
-};
+#include <subdev/fb.h>
+#include <subdev/timer.h>
+#include <engine/gr.h>
 
 static void
-nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2])
+nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2])
 {
        u64 phys = 0xdeadcafe00000000ULL;
        u32 coverage = 0;
 
        if (pgt[0]) {
-               phys = 0x00000003 | pgt[0]->addr; /* present, 4KiB pages */
-               coverage = (pgt[0]->size >> 3) << 12;
+               /* present, 4KiB pages */
+               phys = 0x00000003 | nvkm_memory_addr(pgt[0]);
+               coverage = (nvkm_memory_size(pgt[0]) >> 3) << 12;
        } else
        if (pgt[1]) {
-               phys = 0x00000001 | pgt[1]->addr; /* present */
-               coverage = (pgt[1]->size >> 3) << 16;
+               /* present, 64KiB pages  */
+               phys = 0x00000001 | nvkm_memory_addr(pgt[1]);
+               coverage = (nvkm_memory_size(pgt[1]) >> 3) << 16;
        }
 
        if (phys & 1) {
@@ -57,8 +54,10 @@ nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_gpuobj *pgt[2])
                        phys |= 0x20;
        }
 
-       nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
-       nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
+       nvkm_kmap(pgd);
+       nvkm_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys));
+       nvkm_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys));
+       nvkm_done(pgd);
 }
 
 static inline u64
@@ -75,17 +74,18 @@ vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target)
 }
 
 static void
-nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv50_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt,
            struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
 {
+       struct nvkm_ram *ram = vma->vm->mmu->subdev.device->fb->ram;
        u32 comp = (mem->memtype & 0x180) >> 7;
        u32 block, target;
        int i;
 
        /* IGPs don't have real VRAM, re-target to stolen system memory */
        target = 0;
-       if (nvkm_fb(vma->vm->mmu)->ram->stolen) {
-               phys += nvkm_fb(vma->vm->mmu)->ram->stolen;
+       if (ram->stolen) {
+               phys += ram->stolen;
                target = 3;
        }
 
@@ -93,6 +93,7 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
        pte <<= 3;
        cnt <<= 3;
 
+       nvkm_kmap(pgt);
        while (cnt) {
                u32 offset_h = upper_32_bits(phys);
                u32 offset_l = lower_32_bits(phys);
@@ -113,129 +114,118 @@ nv50_vm_map(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
                }
 
                while (block) {
-                       nv_wo32(pgt, pte + 0, offset_l);
-                       nv_wo32(pgt, pte + 4, offset_h);
+                       nvkm_wo32(pgt, pte + 0, offset_l);
+                       nvkm_wo32(pgt, pte + 4, offset_h);
                        pte += 8;
                        block -= 8;
                }
        }
+       nvkm_done(pgt);
 }
 
 static void
-nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
               struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
        u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2;
        pte <<= 3;
+       nvkm_kmap(pgt);
        while (cnt--) {
                u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target);
-               nv_wo32(pgt, pte + 0, lower_32_bits(phys));
-               nv_wo32(pgt, pte + 4, upper_32_bits(phys));
+               nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
+               nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
                pte += 8;
        }
+       nvkm_done(pgt);
 }
 
 static void
-nv50_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv50_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
 {
        pte <<= 3;
+       nvkm_kmap(pgt);
        while (cnt--) {
-               nv_wo32(pgt, pte + 0, 0x00000000);
-               nv_wo32(pgt, pte + 4, 0x00000000);
+               nvkm_wo32(pgt, pte + 0, 0x00000000);
+               nvkm_wo32(pgt, pte + 4, 0x00000000);
                pte += 8;
        }
+       nvkm_done(pgt);
 }
 
 static void
 nv50_vm_flush(struct nvkm_vm *vm)
 {
-       struct nv50_mmu_priv *priv = (void *)vm->mmu;
-       struct nvkm_bar *bar = nvkm_bar(priv);
-       struct nvkm_engine *engine;
+       struct nvkm_mmu *mmu = vm->mmu;
+       struct nvkm_subdev *subdev = &mmu->subdev;
+       struct nvkm_device *device = subdev->device;
        int i, vme;
 
-       bar->flush(bar);
-
-       mutex_lock(&nv_subdev(priv)->mutex);
-       for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+       mutex_lock(&subdev->mutex);
+       for (i = 0; i < NVKM_SUBDEV_NR; i++) {
                if (!atomic_read(&vm->engref[i]))
                        continue;
 
                /* unfortunate hw bug workaround... */
-               engine = nvkm_engine(priv, i);
-               if (engine && engine->tlb_flush) {
-                       engine->tlb_flush(engine);
-                       continue;
+               if (i == NVKM_ENGINE_GR && device->gr) {
+                       int ret = nvkm_gr_tlb_flush(device->gr);
+                       if (ret != -ENODEV)
+                               continue;
                }
 
                switch (i) {
-               case NVDEV_ENGINE_GR    : vme = 0x00; break;
-               case NVDEV_ENGINE_VP    :
-               case NVDEV_ENGINE_MSPDEC: vme = 0x01; break;
-               case NVDEV_SUBDEV_BAR   : vme = 0x06; break;
-               case NVDEV_ENGINE_MSPPP :
-               case NVDEV_ENGINE_MPEG  : vme = 0x08; break;
-               case NVDEV_ENGINE_BSP   :
-               case NVDEV_ENGINE_MSVLD : vme = 0x09; break;
-               case NVDEV_ENGINE_CIPHER:
-               case NVDEV_ENGINE_SEC   : vme = 0x0a; break;
-               case NVDEV_ENGINE_CE0   : vme = 0x0d; break;
+               case NVKM_ENGINE_GR    : vme = 0x00; break;
+               case NVKM_ENGINE_VP    :
+               case NVKM_ENGINE_MSPDEC: vme = 0x01; break;
+               case NVKM_SUBDEV_BAR   : vme = 0x06; break;
+               case NVKM_ENGINE_MSPPP :
+               case NVKM_ENGINE_MPEG  : vme = 0x08; break;
+               case NVKM_ENGINE_BSP   :
+               case NVKM_ENGINE_MSVLD : vme = 0x09; break;
+               case NVKM_ENGINE_CIPHER:
+               case NVKM_ENGINE_SEC   : vme = 0x0a; break;
+               case NVKM_ENGINE_CE0   : vme = 0x0d; break;
                default:
                        continue;
                }
 
-               nv_wr32(priv, 0x100c80, (vme << 16) | 1);
-               if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000))
-                       nv_error(priv, "vm flush timeout: engine %d\n", vme);
+               nvkm_wr32(device, 0x100c80, (vme << 16) | 1);
+               if (nvkm_msec(device, 2000,
+                       if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
+                               break;
+               ) < 0)
+                       nvkm_error(subdev, "vm flush timeout: engine %d\n", vme);
        }
-       mutex_unlock(&nv_subdev(priv)->mutex);
+       mutex_unlock(&subdev->mutex);
 }
 
 static int
-nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length,
-              u64 mm_offset, struct nvkm_vm **pvm)
+nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
+              struct lock_class_key *key, struct nvkm_vm **pvm)
 {
-       u32 block = (1 << (mmu->pgt_bits + 12));
+       u32 block = (1 << (mmu->func->pgt_bits + 12));
        if (block > length)
                block = length;
 
-       return nvkm_vm_create(mmu, offset, length, mm_offset, block, pvm);
+       return nvkm_vm_create(mmu, offset, length, mm_offset, block, key, pvm);
 }
 
-static int
-nv50_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-             struct nvkm_oclass *oclass, void *data, u32 size,
-             struct nvkm_object **pobject)
+static const struct nvkm_mmu_func
+nv50_mmu = {
+       .limit = (1ULL << 40),
+       .dma_bits = 40,
+       .pgt_bits  = 29 - 12,
+       .spg_shift = 12,
+       .lpg_shift = 16,
+       .create = nv50_vm_create,
+       .map_pgt = nv50_vm_map_pgt,
+       .map = nv50_vm_map,
+       .map_sg = nv50_vm_map_sg,
+       .unmap = nv50_vm_unmap,
+       .flush = nv50_vm_flush,
+};
+
+int
+nv50_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
 {
-       struct nv50_mmu_priv *priv;
-       int ret;
-
-       ret = nvkm_mmu_create(parent, engine, oclass, "VM", "vm", &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.limit = 1ULL << 40;
-       priv->base.dma_bits = 40;
-       priv->base.pgt_bits  = 29 - 12;
-       priv->base.spg_shift = 12;
-       priv->base.lpg_shift = 16;
-       priv->base.create = nv50_vm_create;
-       priv->base.map_pgt = nv50_vm_map_pgt;
-       priv->base.map = nv50_vm_map;
-       priv->base.map_sg = nv50_vm_map_sg;
-       priv->base.unmap = nv50_vm_unmap;
-       priv->base.flush = nv50_vm_flush;
-       return 0;
+       return nvkm_mmu_new_(&nv50_mmu, device, index, pmmu);
 }
-
-struct nvkm_oclass
-nv50_mmu_oclass = {
-       .handle = NV_SUBDEV(MMU, 0x50),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_mmu_ctor,
-               .dtor = _nvkm_mmu_dtor,
-               .init = _nvkm_mmu_init,
-               .fini = _nvkm_mmu_fini,
-       },
-};