drm/nv44/vm: fix and enable use of "real" pciegart
authorBen Skeggs <bskeggs@redhat.com>
Wed, 26 Sep 2012 22:55:53 +0000 (08:55 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 3 Oct 2012 03:13:17 +0000 (13:13 +1000)
Something seems to be missing in regards to flushing specific ranges of
the TLB.  For the moment, flushing the entire thing seems to make it
work alright.

Should give 39-bit DMA addressing on the relevant chipsets.

v2: allocate contig 16KiB for dummy pages, reported by mwk on irc

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c

index 320ccc4..18de4c5 100644 (file)
@@ -218,7 +218,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -238,7 +238,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -258,7 +258,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -278,7 +278,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -298,7 +298,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -338,7 +338,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
@@ -358,7 +358,7 @@ nv40_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
                device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
                device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
-               device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass;
                device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
                device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
                device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
index ad6ad5d..6adbbc9 100644 (file)
@@ -132,10 +132,9 @@ nv04_vmmgr_dtor(struct nouveau_object *object)
                nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
                nouveau_vm_ref(NULL, &priv->vm, NULL);
        }
-       if (priv->page) {
-               pci_unmap_page(nv_device(priv)->pdev, priv->null,
-                              PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-               __free_page(priv->page);
+       if (priv->nullp) {
+               pci_free_consistent(nv_device(priv)->pdev, 16 * 1024,
+                                   priv->nullp, priv->null);
        }
        nouveau_vmmgr_destroy(&priv->base);
 }
index e21369c..ec42d4b 100644 (file)
@@ -6,8 +6,8 @@
 struct nv04_vmmgr_priv {
        struct nouveau_vmmgr base;
        struct nouveau_vm *vm;
-       struct page *page;
        dma_addr_t null;
+       void *nullp;
 };
 
 static inline struct nv04_vmmgr_priv *
index 8c9cece..0ac18d0 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <core/gpuobj.h>
+#include <core/option.h>
 
 #include <subdev/timer.h>
 #include <subdev/vm.h>
  ******************************************************************************/
 
 static void
-nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size)
-{
-       nv_wr32(priv, 0x100814, (size - 1) << 12);
-       nv_wr32(priv, 0x100808, base | 0x20);
-       if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
-               nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
-       nv_wr32(priv, 0x100808, 0x00000000);
-}
-
-static void
 nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
             dma_addr_t *list, u32 pte, u32 cnt)
 {
@@ -57,6 +48,7 @@ nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
        tmp[1] = nv_ro32(pgt, base + 0x4);
        tmp[2] = nv_ro32(pgt, base + 0x8);
        tmp[3] = nv_ro32(pgt, base + 0xc);
+
        while (cnt--) {
                u32 addr = list ? (*list++ >> 12) : (null >> 12);
                switch (pte++ & 0x3) {
@@ -96,8 +88,6 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
               struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
        struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm;
-       u32 base = pte << 12;
-       u32 size = cnt;
        u32 tmp[4];
        int i;
 
@@ -122,15 +112,12 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
        if (cnt)
                nv44_vm_fill(pgt, priv->null, list, pte, cnt);
-       nv44_vm_flush_priv(priv, base, size);
 }
 
 static void
 nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 {
        struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt);
-       u32 base = pte << 12;
-       u32 size = cnt;
 
        if (pte & 3) {
                u32  max = 4 - (pte & 3);
@@ -150,12 +137,17 @@ nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 
        if (cnt)
                nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
-       nv44_vm_flush_priv(priv, base, size);
 }
 
 static void
 nv44_vm_flush(struct nouveau_vm *vm)
 {
+       struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
+       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);
 }
 
 /*******************************************************************************
@@ -171,6 +163,11 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
+       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+               return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
+                                          data, size, pobject);
+       }
+
        ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART",
                                   "pciegart", &priv);
        *pobject = nv_object(priv);
@@ -187,20 +184,12 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        priv->base.unmap = nv44_vm_unmap;
        priv->base.flush = nv44_vm_flush;
 
-       priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL);
-       if (priv->page) {
-               priv->null = pci_map_page(device->pdev, priv->page, 0,
-                                         PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->null)) {
-                       __free_page(priv->page);
-                       priv->page = NULL;
-                       priv->null = 0;
-               }
+       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;
        }
 
-       if (!priv->page)
-               nv_warn(priv, "unable to allocate dummy page\n");
-
        ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
                                &priv->vm);
        if (ret)