浏览代码

drm/nv44/vm: fix and enable use of "real" pciegart

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>
Ben Skeggs 12 年之前
父节点
当前提交
e5f186c4f9

+ 8 - 8
drivers/gpu/drm/nouveau/core/subdev/device/nv40.c

@@ -218,7 +218,7 @@ nv40_identify(struct nouveau_device *device)
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_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_TIMER  ] = &nv04_timer_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass;
 		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_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_DMAOBJ ] = &nv04_dmaeng_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;
 		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass;

+ 3 - 4
drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c

@@ -132,10 +132,9 @@ nv04_vmmgr_dtor(struct nouveau_object *object)
 		nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
 		nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
 		nouveau_vm_ref(NULL, &priv->vm, NULL);
 		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);
 	nouveau_vmmgr_destroy(&priv->base);
 }
 }

+ 1 - 1
drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h

@@ -6,8 +6,8 @@
 struct nv04_vmmgr_priv {
 struct nv04_vmmgr_priv {
 	struct nouveau_vmmgr base;
 	struct nouveau_vmmgr base;
 	struct nouveau_vm *vm;
 	struct nouveau_vm *vm;
-	struct page *page;
 	dma_addr_t null;
 	dma_addr_t null;
+	void *nullp;
 };
 };
 
 
 static inline struct nv04_vmmgr_priv *
 static inline struct nv04_vmmgr_priv *

+ 17 - 28
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c

@@ -23,6 +23,7 @@
  */
  */
 
 
 #include <core/gpuobj.h>
 #include <core/gpuobj.h>
+#include <core/option.h>
 
 
 #include <subdev/timer.h>
 #include <subdev/timer.h>
 #include <subdev/vm.h>
 #include <subdev/vm.h>
@@ -36,16 +37,6 @@
  * VM map/unmap callbacks
  * VM map/unmap callbacks
  ******************************************************************************/
  ******************************************************************************/
 
 
-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
 static void
 nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
 nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
 	     dma_addr_t *list, u32 pte, u32 cnt)
 	     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[1] = nv_ro32(pgt, base + 0x4);
 	tmp[2] = nv_ro32(pgt, base + 0x8);
 	tmp[2] = nv_ro32(pgt, base + 0x8);
 	tmp[3] = nv_ro32(pgt, base + 0xc);
 	tmp[3] = nv_ro32(pgt, base + 0xc);
+
 	while (cnt--) {
 	while (cnt--) {
 		u32 addr = list ? (*list++ >> 12) : (null >> 12);
 		u32 addr = list ? (*list++ >> 12) : (null >> 12);
 		switch (pte++ & 0x3) {
 		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 nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
 {
 	struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm;
 	struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm;
-	u32 base = pte << 12;
-	u32 size = cnt;
 	u32 tmp[4];
 	u32 tmp[4];
 	int i;
 	int i;
 
 
@@ -122,15 +112,12 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
 
 	if (cnt)
 	if (cnt)
 		nv44_vm_fill(pgt, priv->null, list, pte, cnt);
 		nv44_vm_fill(pgt, priv->null, list, pte, cnt);
-	nv44_vm_flush_priv(priv, base, size);
 }
 }
 
 
 static void
 static void
 nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 {
 {
 	struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt);
 	struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt);
-	u32 base = pte << 12;
-	u32 size = cnt;
 
 
 	if (pte & 3) {
 	if (pte & 3) {
 		u32  max = 4 - (pte & 3);
 		u32  max = 4 - (pte & 3);
@@ -150,12 +137,17 @@ nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 
 
 	if (cnt)
 	if (cnt)
 		nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
 		nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
-	nv44_vm_flush_priv(priv, base, size);
 }
 }
 
 
 static void
 static void
 nv44_vm_flush(struct nouveau_vm *vm)
 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;
 	struct nv04_vmmgr_priv *priv;
 	int ret;
 	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",
 	ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART",
 				   "pciegart", &priv);
 				   "pciegart", &priv);
 	*pobject = nv_object(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.unmap = nv44_vm_unmap;
 	priv->base.flush = nv44_vm_flush;
 	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,
 	ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
 				&priv->vm);
 				&priv->vm);
 	if (ret)
 	if (ret)