drm/nv50/vm: handle bar tlb flushes internally
authorBen Skeggs <bskeggs@redhat.com>
Mon, 13 May 2013 10:41:18 +0000 (20:41 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 1 Jul 2013 03:44:37 +0000 (13:44 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/include/subdev/vm.h
drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c

index 9d595efe667a9703d59151b43ddbb1c2eaeffa96..c888f93e0ee628bb46fd42d231d41b637e8d6257 100644 (file)
@@ -58,7 +58,7 @@ struct nouveau_vm {
        int refcount;
 
        struct list_head pgd_list;
-       atomic_t engref[64]; //NVDEV_SUBDEV_NR];
+       atomic_t engref[NVDEV_SUBDEV_NR];
 
        struct nouveau_vm_pgt *pgt;
        u32 fpde;
index 649f1ced1fe0919e983d0587515b98079909362a..160d27f3c7b4732fc67a069a415681295a0d8dd4 100644 (file)
@@ -53,7 +53,6 @@ nv50_bar_kmap(struct nouveau_bar *bar, struct nouveau_mem *mem,
                return ret;
 
        nouveau_vm_map(vma, mem);
-       nv50_vm_flush_engine(nv_subdev(bar), 6);
        return 0;
 }
 
@@ -69,7 +68,6 @@ nv50_bar_umap(struct nouveau_bar *bar, struct nouveau_mem *mem,
                return ret;
 
        nouveau_vm_map(vma, mem);
-       nv50_vm_flush_engine(nv_subdev(bar), 6);
        return 0;
 }
 
@@ -77,7 +75,6 @@ static void
 nv50_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma)
 {
        nouveau_vm_unmap(vma);
-       nv50_vm_flush_engine(nv_subdev(bar), 6);
        nouveau_vm_put(vma);
 }
 
@@ -147,6 +144,8 @@ nv50_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), heap,
                                 ((limit-- - start) >> 12) * 8, 0x1000,
                                 NVOBJ_FLAG_ZERO_ALLOC, &vm->pgt[0].obj[0]);
@@ -179,6 +178,8 @@ nv50_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->bar1_vm, priv->pgd);
        nouveau_vm_ref(NULL, &vm, NULL);
        if (ret)
@@ -237,7 +238,11 @@ nv50_bar_init(struct nouveau_object *object)
 
        nv_mask(priv, 0x000200, 0x00000100, 0x00000000);
        nv_mask(priv, 0x000200, 0x00000100, 0x00000100);
-       nv50_vm_flush_engine(nv_subdev(priv), 6);
+       nv_wr32(priv, 0x100c80, 0x00060001);
+       if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000)) {
+               nv_error(priv, "vm flush timeout\n");
+               return -EBUSY;
+       }
 
        nv_wr32(priv, 0x001704, 0x00000000 | priv->mem->addr >> 12);
        nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12);
index 3a3693e743671c5bc1399abd1f08f2f80f53b70f..6ed85efd89b26f7d1b309395d334014a4c2d6c4c 100644 (file)
@@ -155,6 +155,9 @@ nv50_vm_flush(struct nouveau_vm *vm)
        int i;
 
        for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+               if (atomic_read(&vm->engref[i]) && i == NVDEV_SUBDEV_BAR) {
+                       nv50_vm_flush_engine(nv_subdev(vm->vmm), 6);
+               } else
                if (atomic_read(&vm->engref[i])) {
                        engine = nouveau_engine(vm->vmm, i);
                        if (engine && engine->tlb_flush)