These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / mmu / nv44.c
index b90ded1..a648c23 100644 (file)
@@ -23,7 +23,6 @@
  */
 #include "nv04.h"
 
-#include <core/device.h>
 #include <core/gpuobj.h>
 #include <core/option.h>
 #include <subdev/timer.h>
  ******************************************************************************/
 
 static void
-nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null,
+nv44_vm_fill(struct nvkm_memory *pgt, dma_addr_t null,
             dma_addr_t *list, u32 pte, u32 cnt)
 {
        u32 base = (pte << 2) & ~0x0000000f;
        u32 tmp[4];
 
-       tmp[0] = nv_ro32(pgt, base + 0x0);
-       tmp[1] = nv_ro32(pgt, base + 0x4);
-       tmp[2] = nv_ro32(pgt, base + 0x8);
-       tmp[3] = nv_ro32(pgt, base + 0xc);
+       tmp[0] = nvkm_ro32(pgt, base + 0x0);
+       tmp[1] = nvkm_ro32(pgt, base + 0x4);
+       tmp[2] = nvkm_ro32(pgt, base + 0x8);
+       tmp[3] = nvkm_ro32(pgt, base + 0xc);
 
        while (cnt--) {
                u32 addr = list ? (*list++ >> 12) : (null >> 12);
@@ -75,24 +74,25 @@ nv44_vm_fill(struct nvkm_gpuobj *pgt, dma_addr_t null,
                }
        }
 
-       nv_wo32(pgt, base + 0x0, tmp[0]);
-       nv_wo32(pgt, base + 0x4, tmp[1]);
-       nv_wo32(pgt, base + 0x8, tmp[2]);
-       nv_wo32(pgt, base + 0xc, tmp[3] | 0x40000000);
+       nvkm_wo32(pgt, base + 0x0, tmp[0]);
+       nvkm_wo32(pgt, base + 0x4, tmp[1]);
+       nvkm_wo32(pgt, base + 0x8, tmp[2]);
+       nvkm_wo32(pgt, base + 0xc, tmp[3] | 0x40000000);
 }
 
 static void
-nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
+nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
               struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
-       struct nv04_mmu_priv *priv = (void *)vma->vm->mmu;
+       struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
        u32 tmp[4];
        int i;
 
+       nvkm_kmap(pgt);
        if (pte & 3) {
                u32  max = 4 - (pte & 3);
                u32 part = (cnt > max) ? max : cnt;
-               nv44_vm_fill(pgt, priv->null, list, pte, part);
+               nv44_vm_fill(pgt, mmu->null, list, pte, part);
                pte  += part;
                list += part;
                cnt  -= part;
@@ -101,51 +101,57 @@ nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_gpuobj *pgt,
        while (cnt >= 4) {
                for (i = 0; i < 4; i++)
                        tmp[i] = *list++ >> 12;
-               nv_wo32(pgt, pte++ * 4, tmp[0] >>  0 | tmp[1] << 27);
-               nv_wo32(pgt, pte++ * 4, tmp[1] >>  5 | tmp[2] << 22);
-               nv_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17);
-               nv_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000);
+               nvkm_wo32(pgt, pte++ * 4, tmp[0] >>  0 | tmp[1] << 27);
+               nvkm_wo32(pgt, pte++ * 4, tmp[1] >>  5 | tmp[2] << 22);
+               nvkm_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17);
+               nvkm_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000);
                cnt -= 4;
        }
 
        if (cnt)
-               nv44_vm_fill(pgt, priv->null, list, pte, cnt);
+               nv44_vm_fill(pgt, mmu->null, list, pte, cnt);
+       nvkm_done(pgt);
 }
 
 static void
-nv44_vm_unmap(struct nvkm_gpuobj *pgt, u32 pte, u32 cnt)
+nv44_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
 {
-       struct nv04_mmu_priv *priv = (void *)nvkm_mmu(pgt);
+       struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
 
+       nvkm_kmap(pgt);
        if (pte & 3) {
                u32  max = 4 - (pte & 3);
                u32 part = (cnt > max) ? max : cnt;
-               nv44_vm_fill(pgt, priv->null, NULL, pte, part);
+               nv44_vm_fill(pgt, mmu->null, NULL, pte, part);
                pte  += part;
                cnt  -= part;
        }
 
        while (cnt >= 4) {
-               nv_wo32(pgt, pte++ * 4, 0x00000000);
-               nv_wo32(pgt, pte++ * 4, 0x00000000);
-               nv_wo32(pgt, pte++ * 4, 0x00000000);
-               nv_wo32(pgt, pte++ * 4, 0x00000000);
+               nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+               nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+               nvkm_wo32(pgt, pte++ * 4, 0x00000000);
+               nvkm_wo32(pgt, pte++ * 4, 0x00000000);
                cnt -= 4;
        }
 
        if (cnt)
-               nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
+               nv44_vm_fill(pgt, mmu->null, NULL, pte, cnt);
+       nvkm_done(pgt);
 }
 
 static void
 nv44_vm_flush(struct nvkm_vm *vm)
 {
-       struct nv04_mmu_priv *priv = (void *)vm->mmu;
-       nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE);
-       nv_wr32(priv, 0x100808, 0x00000020);
-       if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
-               nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
-       nv_wr32(priv, 0x100808, 0x00000000);
+       struct nv04_mmu *mmu = nv04_mmu(vm->mmu);
+       struct nvkm_device *device = mmu->base.subdev.device;
+       nvkm_wr32(device, 0x100814, mmu->base.limit - NV44_GART_PAGE);
+       nvkm_wr32(device, 0x100808, 0x00000020);
+       nvkm_msec(device, 2000,
+               if (nvkm_rd32(device, 0x100808) & 0x00000001)
+                       break;
+       );
+       nvkm_wr32(device, 0x100808, 0x00000000);
 }
 
 /*******************************************************************************
@@ -153,95 +159,78 @@ nv44_vm_flush(struct nvkm_vm *vm)
  ******************************************************************************/
 
 static int
-nv44_mmu_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-             struct nvkm_oclass *oclass, void *data, u32 size,
-             struct nvkm_object **pobject)
+nv44_mmu_oneinit(struct nvkm_mmu *base)
 {
-       struct nvkm_device *device = nv_device(parent);
-       struct nv04_mmu_priv *priv;
+       struct nv04_mmu *mmu = nv04_mmu(base);
+       struct nvkm_device *device = mmu->base.subdev.device;
        int ret;
 
-       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
-           !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) {
-               return nvkm_object_ctor(parent, engine, &nv04_mmu_oclass,
-                                       data, size, pobject);
-       }
-
-       ret = nvkm_mmu_create(parent, engine, oclass, "PCIEGART",
-                             "pciegart", &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->base.create = nv04_vm_create;
-       priv->base.limit = NV44_GART_SIZE;
-       priv->base.dma_bits = 39;
-       priv->base.pgt_bits = 32 - 12;
-       priv->base.spg_shift = 12;
-       priv->base.lpg_shift = 12;
-       priv->base.map_sg = nv44_vm_map_sg;
-       priv->base.unmap = nv44_vm_unmap;
-       priv->base.flush = nv44_vm_flush;
-
-       priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null);
-       if (!priv->nullp) {
-               nv_error(priv, "unable to allocate dummy pages\n");
-               return -ENOMEM;
+       mmu->nullp = dma_alloc_coherent(device->dev, 16 * 1024,
+                                       &mmu->null, GFP_KERNEL);
+       if (!mmu->nullp) {
+               nvkm_warn(&mmu->base.subdev, "unable to allocate dummy pages\n");
+               mmu->null = 0;
        }
 
-       ret = nvkm_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
-                            &priv->vm);
+       ret = nvkm_vm_create(&mmu->base, 0, NV44_GART_SIZE, 0, 4096, NULL,
+                            &mmu->vm);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(nv_object(priv), NULL,
+       ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
                              (NV44_GART_SIZE / NV44_GART_PAGE) * 4,
-                             512 * 1024, NVOBJ_FLAG_ZERO_ALLOC,
-                             &priv->vm->pgt[0].obj[0]);
-       priv->vm->pgt[0].refcount[0] = 1;
-       if (ret)
-               return ret;
-
-       return 0;
+                             512 * 1024, true,
+                             &mmu->vm->pgt[0].mem[0]);
+       mmu->vm->pgt[0].refcount[0] = 1;
+       return ret;
 }
 
-static int
-nv44_mmu_init(struct nvkm_object *object)
+static void
+nv44_mmu_init(struct nvkm_mmu *base)
 {
-       struct nv04_mmu_priv *priv = (void *)object;
-       struct nvkm_gpuobj *gart = priv->vm->pgt[0].obj[0];
+       struct nv04_mmu *mmu = nv04_mmu(base);
+       struct nvkm_device *device = mmu->base.subdev.device;
+       struct nvkm_memory *gart = mmu->vm->pgt[0].mem[0];
        u32 addr;
-       int ret;
-
-       ret = nvkm_mmu_init(&priv->base);
-       if (ret)
-               return ret;
 
        /* calculate vram address of this PRAMIN block, object must be
         * allocated on 512KiB alignment, and not exceed a total size
         * of 512KiB for this to work correctly
         */
-       addr  = nv_rd32(priv, 0x10020c);
-       addr -= ((gart->addr >> 19) + 1) << 19;
-
-       nv_wr32(priv, 0x100850, 0x80000000);
-       nv_wr32(priv, 0x100818, priv->null);
-       nv_wr32(priv, 0x100804, NV44_GART_SIZE);
-       nv_wr32(priv, 0x100850, 0x00008000);
-       nv_mask(priv, 0x10008c, 0x00000200, 0x00000200);
-       nv_wr32(priv, 0x100820, 0x00000000);
-       nv_wr32(priv, 0x10082c, 0x00000001);
-       nv_wr32(priv, 0x100800, addr | 0x00000010);
-       return 0;
+       addr  = nvkm_rd32(device, 0x10020c);
+       addr -= ((nvkm_memory_addr(gart) >> 19) + 1) << 19;
+
+       nvkm_wr32(device, 0x100850, 0x80000000);
+       nvkm_wr32(device, 0x100818, mmu->null);
+       nvkm_wr32(device, 0x100804, NV44_GART_SIZE);
+       nvkm_wr32(device, 0x100850, 0x00008000);
+       nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200);
+       nvkm_wr32(device, 0x100820, 0x00000000);
+       nvkm_wr32(device, 0x10082c, 0x00000001);
+       nvkm_wr32(device, 0x100800, addr | 0x00000010);
 }
 
-struct nvkm_oclass
-nv44_mmu_oclass = {
-       .handle = NV_SUBDEV(MMU, 0x44),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv44_mmu_ctor,
-               .dtor = nv04_mmu_dtor,
-               .init = nv44_mmu_init,
-               .fini = _nvkm_mmu_fini,
-       },
+static const struct nvkm_mmu_func
+nv44_mmu = {
+       .dtor = nv04_mmu_dtor,
+       .oneinit = nv44_mmu_oneinit,
+       .init = nv44_mmu_init,
+       .limit = NV44_GART_SIZE,
+       .dma_bits = 39,
+       .pgt_bits = 32 - 12,
+       .spg_shift = 12,
+       .lpg_shift = 12,
+       .map_sg = nv44_vm_map_sg,
+       .unmap = nv44_vm_unmap,
+       .flush = nv44_vm_flush,
 };
+
+int
+nv44_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
+{
+       if (device->type == NVKM_DEVICE_AGP ||
+           !nvkm_boolopt(device->cfgopt, "NvPCIE", true))
+               return nv04_mmu_new(device, index, pmmu);
+
+       return nv04_mmu_new_(&nv44_mmu, device, index, pmmu);
+}