浏览代码

drm/nvc0/vm: handle bar tlb flushes internally

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 12 年之前
父节点
当前提交
15cace5917

+ 0 - 2
drivers/gpu/drm/nouveau/core/include/subdev/vm.h

@@ -117,8 +117,6 @@ int  nv04_vm_create(struct nouveau_vmmgr *, u64, u64, u64,
 		    struct nouveau_vm **);
 void nv04_vmmgr_dtor(struct nouveau_object *);
 
-void nvc0_vm_flush_engine(struct nouveau_subdev *, u64 addr, int type);
-
 /* nouveau_vm.c */
 int  nouveau_vm_create(struct nouveau_vmmgr *, u64 offset, u64 length,
 		       u64 mm_offset, u32 block, struct nouveau_vm **);

+ 4 - 6
drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c

@@ -51,7 +51,6 @@ nvc0_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem,
 		return ret;
 
 	nouveau_vm_map(vma, mem);
-	nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[0].pgd->addr, 5);
 	return 0;
 }
 
@@ -68,18 +67,13 @@ nvc0_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem,
 		return ret;
 
 	nouveau_vm_map(vma, mem);
-	nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[1].pgd->addr, 5);
 	return 0;
 }
 
 static void
 nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma)
 {
-	struct nvc0_bar_priv *priv = (void *)bar;
-	int i = !(vma->vm == priv->bar[0].vm);
-
 	nouveau_vm_unmap(vma);
-	nvc0_vm_flush_engine(nv_subdev(bar), priv->bar[i].pgd->addr, 5);
 	nouveau_vm_put(vma);
 }
 
@@ -116,6 +110,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
+	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
+
 	ret = nouveau_gpuobj_new(nv_object(priv), NULL,
 				 (pci_resource_len(pdev, 3) >> 12) * 8,
 				 0x1000, NVOBJ_FLAG_ZERO_ALLOC,
@@ -150,6 +146,8 @@ nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
+	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
+
 	ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd);
 	nouveau_vm_ref(NULL, &vm, NULL);
 	if (ret)

+ 24 - 26
drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c

@@ -159,39 +159,37 @@ nvc0_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 	}
 }
 
-void
-nvc0_vm_flush_engine(struct nouveau_subdev *subdev, u64 addr, int type)
-{
-	struct nvc0_vmmgr_priv *priv = (void *)nouveau_vmmgr(subdev);
-
-	/* looks like maybe a "free flush slots" counter, the
-	 * faster you write to 0x100cbc to more it decreases
-	 */
-	mutex_lock(&nv_subdev(priv)->mutex);
-	if (!nv_wait_ne(subdev, 0x100c80, 0x00ff0000, 0x00000000)) {
-		nv_error(subdev, "vm timeout 0: 0x%08x %d\n",
-			 nv_rd32(subdev, 0x100c80), type);
-	}
-
-	nv_wr32(subdev, 0x100cb8, addr >> 8);
-	nv_wr32(subdev, 0x100cbc, 0x80000000 | type);
-
-	/* wait for flush to be queued? */
-	if (!nv_wait(subdev, 0x100c80, 0x00008000, 0x00008000)) {
-		nv_error(subdev, "vm timeout 1: 0x%08x %d\n",
-			 nv_rd32(subdev, 0x100c80), type);
-	}
-	mutex_unlock(&nv_subdev(priv)->mutex);
-}
-
 static void
 nvc0_vm_flush(struct nouveau_vm *vm)
 {
+	struct nvc0_vmmgr_priv *priv = (void *)vm->vmm;
 	struct nouveau_vm_pgd *vpgd;
+	u32 type;
 
+	type = 0x00000001; /* PAGE_ALL */
+	if (atomic_read(&vm->engref[NVDEV_SUBDEV_BAR]))
+		type |= 0x00000004; /* HUB_ONLY */
+
+	mutex_lock(&nv_subdev(priv)->mutex);
 	list_for_each_entry(vpgd, &vm->pgd_list, head) {
-		nvc0_vm_flush_engine(nv_subdev(vm->vmm), vpgd->obj->addr, 1);
+		/* looks like maybe a "free flush slots" counter, the
+		 * faster you write to 0x100cbc to more it decreases
+		 */
+		if (!nv_wait_ne(priv, 0x100c80, 0x00ff0000, 0x00000000)) {
+			nv_error(priv, "vm timeout 0: 0x%08x %d\n",
+				 nv_rd32(priv, 0x100c80), type);
+		}
+
+		nv_wr32(priv, 0x100cb8, vpgd->obj->addr >> 8);
+		nv_wr32(priv, 0x100cbc, 0x80000000 | type);
+
+		/* wait for flush to be queued? */
+		if (!nv_wait(priv, 0x100c80, 0x00008000, 0x00008000)) {
+			nv_error(priv, "vm timeout 1: 0x%08x %d\n",
+				 nv_rd32(priv, 0x100c80), type);
+		}
 	}
+	mutex_unlock(&nv_subdev(priv)->mutex);
 }
 
 static int