]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/nv50: implement global channel address space on new VM code
authorBen Skeggs <bskeggs@redhat.com>
Mon, 15 Nov 2010 01:54:21 +0000 (11:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 8 Dec 2010 03:48:13 +0000 (13:48 +1000)
As of this commit, it's guaranteed that if an object is in VRAM that its
GPU virtual address will be constant.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
13 files changed:
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_object.c
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_instmem.c
drivers/gpu/drm/nouveau/nv50_vm.c
drivers/gpu/drm/nouveau/nv84_crypt.c

index 4d142031d54267f14cd8bcbbbed10abed5130b9f..203e75de4128bf44b73d51e567d5c81dbce87523 100644 (file)
@@ -49,6 +49,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
                DRM_ERROR("bo %p still attached to GEM object\n", bo);
 
        nv10_mem_put_tile_region(dev, nvbo->tile, NULL);
+       nouveau_vm_put(&nvbo->vma);
        kfree(nvbo);
 }
 
@@ -113,6 +114,15 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
                               &align, &size);
        align >>= PAGE_SHIFT;
 
+       if (!nvbo->no_vm && dev_priv->chan_vm) {
+               ret = nouveau_vm_get(dev_priv->chan_vm, size, 16,
+                                    NV_MEM_ACCESS_RW, &nvbo->vma);
+               if (ret) {
+                       kfree(nvbo);
+                       return ret;
+               }
+       }
+
        nouveau_bo_placement_set(nvbo, flags, 0);
 
        nvbo->channel = chan;
@@ -125,6 +135,11 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
        }
        nvbo->channel = NULL;
 
+       if (nvbo->vma.node) {
+               if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+                       nvbo->bo.offset = nvbo->vma.offset;
+       }
+
        *pnvbo = nvbo;
        return 0;
 }
@@ -294,6 +309,11 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
        if (ret)
                return ret;
 
+       if (nvbo->vma.node) {
+               if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
+                       nvbo->bo.offset = nvbo->vma.offset;
+       }
+
        return 0;
 }
 
@@ -400,10 +420,7 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
                man->available_caching = TTM_PL_FLAG_UNCACHED |
                                         TTM_PL_FLAG_WC;
                man->default_caching = TTM_PL_FLAG_WC;
-               if (dev_priv->card_type == NV_50)
-                       man->gpu_offset = 0x40000000;
-               else
-                       man->gpu_offset = 0;
+               man->gpu_offset = 0;
                break;
        case TTM_PL_TT:
                man->func = &ttm_bo_manager_func;
@@ -507,12 +524,12 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
        dst_offset = new_mem->start << PAGE_SHIFT;
        if (!nvbo->no_vm) {
                if (old_mem->mem_type == TTM_PL_VRAM)
-                       src_offset += dev_priv->vm_vram_base;
+                       src_offset  = nvbo->vma.offset;
                else
                        src_offset += dev_priv->vm_gart_base;
 
                if (new_mem->mem_type == TTM_PL_VRAM)
-                       dst_offset += dev_priv->vm_vram_base;
+                       dst_offset  = nvbo->vma.offset;
                else
                        dst_offset += dev_priv->vm_gart_base;
        }
@@ -756,7 +773,6 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
        struct drm_device *dev = dev_priv->dev;
        struct nouveau_bo *nvbo = nouveau_bo(bo);
        uint64_t offset;
-       int ret;
 
        if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
                /* Nothing to do. */
@@ -766,15 +782,8 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
 
        offset = new_mem->start << PAGE_SHIFT;
 
-       if (dev_priv->card_type == NV_50) {
-               ret = nv50_mem_vm_bind_linear(dev,
-                                             offset + dev_priv->vm_vram_base,
-                                             new_mem->size,
-                                             nouveau_bo_tile_layout(nvbo),
-                                             offset);
-               if (ret)
-                       return ret;
-
+       if (dev_priv->chan_vm) {
+               nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
        } else if (dev_priv->card_type >= NV_10) {
                *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
                                                nvbo->tile_mode,
index a3d33a582a984260689ab4e81d3e5e3f8f3c01b3..6f37995aee2d597c7c1a5b6c4329a29d1a9b19b8 100644 (file)
@@ -39,7 +39,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
 
        if (dev_priv->card_type >= NV_50) {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
-                                            dev_priv->vm_end, NV_MEM_ACCESS_RO,
+                                            (1ULL << 40), NV_MEM_ACCESS_RO,
                                             NV_MEM_TARGET_VM, &pushbuf);
                chan->pushbuf_base = pb->bo.offset;
        } else
index a48c7da133d2cc1fb6d921ff7e8869ed94ff5634..bb170570938be046e221e18159741199c7c36b9b 100644 (file)
@@ -339,13 +339,11 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+               u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT;
 
-               nv_crtc->cursor.set_offset(nv_crtc,
-                                       nv_crtc->cursor.nvbo->bo.offset -
-                                       dev_priv->vm_vram_base);
-
+               nv_crtc->cursor.set_offset(nv_crtc, offset);
                nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
-                       nv_crtc->cursor_saved_y);
+                                                nv_crtc->cursor_saved_y);
        }
 
        /* Force CLUT to get re-loaded during modeset */
index 452a8652a4984185019a290e3fde990b9a76698e..dce9a5f6f6c4f128d0794bd3ff309c76267d6c0a 100644 (file)
@@ -65,10 +65,6 @@ struct nouveau_vram;
 #define NOUVEAU_MAX_CHANNEL_NR 128
 #define NOUVEAU_MAX_TILE_NR 15
 
-#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL)
-#define NV50_VM_BLOCK    (512*1024*1024ULL)
-#define NV50_VM_VRAM_NR  (NV50_VM_MAX_VRAM / NV50_VM_BLOCK)
-
 struct nouveau_vram {
        struct drm_device *dev;
 
@@ -106,6 +102,7 @@ struct nouveau_bo {
 
        struct nouveau_channel *channel;
 
+       struct nouveau_vma vma;
        bool mappable;
        bool no_vm;
 
@@ -252,7 +249,6 @@ struct nouveau_channel {
        struct nouveau_vm     *vm;
        struct nouveau_gpuobj *vm_pd;
        struct nouveau_gpuobj *vm_gart_pt;
-       struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
 
        /* Objects */
        struct nouveau_gpuobj *ramin; /* Private instmem */
@@ -712,13 +708,9 @@ struct drm_nouveau_private {
        struct nouveau_vm *bar3_vm;
 
        /* G8x/G9x virtual address space */
+       struct nouveau_vm *chan_vm;
        uint64_t vm_gart_base;
        uint64_t vm_gart_size;
-       uint64_t vm_vram_base;
-       uint64_t vm_vram_size;
-       uint64_t vm_end;
-       struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
-       int vm_vram_pt_nr;
 
        struct nvbios vbios;
 
@@ -836,11 +828,6 @@ extern struct nouveau_tile_reg *nv10_mem_set_tiling(
 extern void nv10_mem_put_tile_region(struct drm_device *dev,
                                     struct nouveau_tile_reg *tile,
                                     struct nouveau_fence *fence);
-extern int  nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt,
-                                   uint32_t size, uint32_t flags,
-                                   uint64_t phys);
-extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt,
-                              uint32_t size);
 extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
 
 /* nouveau_notifier.c */
index 0fce4eb914d5b5837bf4beba9f6db7f9aac63028..ea861c91514952b5c84170242c4fcc451f2adf05 100644 (file)
@@ -338,8 +338,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
                              FBINFO_HWACCEL_IMAGEBLIT;
        info->flags |= FBINFO_CAN_FORCE_OUTPUT;
        info->fbops = &nouveau_fbcon_sw_ops;
-       info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
-                              dev_priv->vm_vram_base;
+       info->fix.smem_start = dev->mode_config.fb_base +
+                              (nvbo->bo.mem.start << PAGE_SHIFT);
        info->fix.smem_len = size;
 
        info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
index 2d02401e8227922ce0bdff61c01e1a26a28ee35a..4d2d3de97ee955b4516c2159eb506f9a14b7ea10 100644 (file)
@@ -144,100 +144,6 @@ nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size,
        return found;
 }
 
-/*
- * NV50 VM helpers
- */
-int
-nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
-                       uint32_t flags, uint64_t phys)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_gpuobj *pgt;
-       unsigned block;
-       int i;
-
-       virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1;
-       size = (size >> 16) << 1;
-
-       phys |= ((uint64_t)flags << 32);
-       phys |= 1;
-       if (dev_priv->vram_sys_base) {
-               phys += dev_priv->vram_sys_base;
-               phys |= 0x30;
-       }
-
-       while (size) {
-               unsigned offset_h = upper_32_bits(phys);
-               unsigned offset_l = lower_32_bits(phys);
-               unsigned pte, end;
-
-               for (i = 7; i >= 0; i--) {
-                       block = 1 << (i + 1);
-                       if (size >= block && !(virt & (block - 1)))
-                               break;
-               }
-               offset_l |= (i << 7);
-
-               phys += block << 15;
-               size -= block;
-
-               while (block) {
-                       pgt = dev_priv->vm_vram_pt[virt >> 14];
-                       pte = virt & 0x3ffe;
-
-                       end = pte + block;
-                       if (end > 16384)
-                               end = 16384;
-                       block -= (end - pte);
-                       virt  += (end - pte);
-
-                       while (pte < end) {
-                               nv_wo32(pgt, (pte * 4) + 0, offset_l);
-                               nv_wo32(pgt, (pte * 4) + 4, offset_h);
-                               pte += 2;
-                       }
-               }
-       }
-
-       dev_priv->engine.instmem.flush(dev);
-       dev_priv->engine.fifo.tlb_flush(dev);
-       dev_priv->engine.graph.tlb_flush(dev);
-       nv50_vm_flush_engine(dev, 6);
-       return 0;
-}
-
-void
-nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_gpuobj *pgt;
-       unsigned pages, pte, end;
-
-       virt -= dev_priv->vm_vram_base;
-       pages = (size >> 16) << 1;
-
-       while (pages) {
-               pgt = dev_priv->vm_vram_pt[virt >> 29];
-               pte = (virt & 0x1ffe0000ULL) >> 15;
-
-               end = pte + pages;
-               if (end > 16384)
-                       end = 16384;
-               pages -= (end - pte);
-               virt  += (end - pte) << 15;
-
-               while (pte < end) {
-                       nv_wo32(pgt, (pte * 4), 0);
-                       pte++;
-               }
-       }
-
-       dev_priv->engine.instmem.flush(dev);
-       dev_priv->engine.fifo.tlb_flush(dev);
-       dev_priv->engine.graph.tlb_flush(dev);
-       nv50_vm_flush_engine(dev, 6);
-}
-
 /*
  * Cleanup everything
  */
index dd1859f7d8b0a12f11bb875c1be1925e44b29117..573fd7316d638c1d5af2823626d4e379861ff1a1 100644 (file)
@@ -35,6 +35,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_ramht.h"
+#include "nouveau_vm.h"
 
 struct nouveau_gpuobj_method {
        struct list_head head;
@@ -770,9 +771,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
        struct nouveau_gpuobj *vram = NULL, *tt = NULL;
-       int ret, i;
+       int ret;
 
        NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 
@@ -783,16 +783,14 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                return ret;
        }
 
-       /* NV50 VM
+       /* NV50/NVC0 VM
         *  - Allocate per-channel page-directory
-        *  - Map GART and VRAM into the channel's address space at the
-        *    locations determined during init.
+        *  - Link with shared channel VM
         */
-       if (dev_priv->card_type >= NV_50) {
+       if (dev_priv->chan_vm) {
                u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
                u64 vm_vinst = chan->ramin->vinst + pgd_offs;
                u32 vm_pinst = chan->ramin->pinst;
-               u32 pde;
 
                if (vm_pinst != ~0)
                        vm_pinst += pgd_offs;
@@ -801,29 +799,9 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                                              0, &chan->vm_pd);
                if (ret)
                        return ret;
-               for (i = 0; i < 0x4000; i += 8) {
-                       nv_wo32(chan->vm_pd, i + 0, 0x00000000);
-                       nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe);
-               }
-
-               nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma,
-                                  &chan->vm_gart_pt);
-               pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8;
-               nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3);
-               nv_wo32(chan->vm_pd, pde + 4, 0x00000000);
-
-               pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8;
-               for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
-                       nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i],
-                                          &chan->vm_vram_pt[i]);
-
-                       nv_wo32(chan->vm_pd, pde + 0,
-                               chan->vm_vram_pt[i]->vinst | 0x61);
-                       nv_wo32(chan->vm_pd, pde + 4, 0x00000000);
-                       pde += 8;
-               }
 
-               instmem->flush(dev);
+               nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
+               chan->vm->map_pgt(chan->vm_pd, 12, 1, dev_priv->gart_info.sg_ctxdma);
        }
 
        /* RAMHT */
@@ -846,8 +824,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
        /* VRAM ctxdma */
        if (dev_priv->card_type >= NV_50) {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-                                            0, dev_priv->vm_end,
-                                            NV_MEM_ACCESS_RW,
+                                            0, (1ULL << 40), NV_MEM_ACCESS_RW,
                                             NV_MEM_TARGET_VM, &vram);
                if (ret) {
                        NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
@@ -874,8 +851,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
        /* TT memory ctxdma */
        if (dev_priv->card_type >= NV_50) {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-                                            0, dev_priv->vm_end,
-                                            NV_MEM_ACCESS_RW,
+                                            0, (1ULL << 40), NV_MEM_ACCESS_RW,
                                             NV_MEM_TARGET_VM, &tt);
        } else {
                ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
@@ -902,9 +878,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 void
 nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 {
-       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct drm_device *dev = chan->dev;
-       int i;
 
        NV_DEBUG(dev, "ch%d\n", chan->id);
 
@@ -913,10 +887,9 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 
        nouveau_ramht_ref(NULL, &chan->ramht, chan);
 
+       nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
        nouveau_gpuobj_ref(NULL, &chan->vm_pd);
        nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt);
-       for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
-               nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]);
 
        if (chan->ramin_heap.free_stack.next)
                drm_mm_takedown(&chan->ramin_heap);
index f3570cc450175b2b882adc3e207a853761a4a5aa..2c346f797285e973645dc893747288a4d4466e08 100644 (file)
@@ -345,7 +345,6 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
                     uint32_t buffer_handle, uint32_t width, uint32_t height)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_bo *cursor = NULL;
        struct drm_gem_object *gem;
@@ -374,8 +373,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 
        nouveau_bo_unmap(cursor);
 
-       nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset -
-                                           dev_priv->vm_vram_base);
+       nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT);
        nv_crtc->cursor.show(nv_crtc, true);
 
 out:
@@ -548,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
                 return -EINVAL;
        }
 
-       nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base;
+       nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
        nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
        nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
        if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) {
index 1567319939079a5c21a5dbce47021c790c6895b8..6d38cb1488ae986dcf01aacb213b5d12e67c9544 100644 (file)
@@ -3,6 +3,7 @@
 #include "nouveau_dma.h"
 #include "nouveau_ramht.h"
 #include "nouveau_fbcon.h"
+#include "nouveau_mm.h"
 
 int
 nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -134,10 +135,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
        struct drm_device *dev = nfbdev->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_channel *chan = dev_priv->channel;
+       struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo;
        int ret, format;
-       uint64_t fb;
-
-       fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base;
 
        switch (info->var.bits_per_pixel) {
        case 8:
@@ -224,8 +223,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
        OUT_RING(chan, info->fix.line_length);
        OUT_RING(chan, info->var.xres_virtual);
        OUT_RING(chan, info->var.yres_virtual);
-       OUT_RING(chan, upper_32_bits(fb));
-       OUT_RING(chan, lower_32_bits(fb));
+       OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
+       OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
        BEGIN_RING(chan, NvSub2D, 0x0230, 2);
        OUT_RING(chan, format);
        OUT_RING(chan, 1);
@@ -233,8 +232,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
        OUT_RING(chan, info->fix.line_length);
        OUT_RING(chan, info->var.xres_virtual);
        OUT_RING(chan, info->var.yres_virtual);
-       OUT_RING(chan, upper_32_bits(fb));
-       OUT_RING(chan, lower_32_bits(fb));
+       OUT_RING(chan, upper_32_bits(nvbo->vma.offset));
+       OUT_RING(chan, lower_32_bits(nvbo->vma.offset));
 
        return 0;
 }
index f5fd1b296d27ae24a3a11dc140593376ef01dd7b..c510e74acf4d5c87706da1d9292dd7d2bd021c29 100644 (file)
@@ -246,6 +246,7 @@ nv50_graph_create_context(struct nouveau_channel *chan)
        nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12);
 
        dev_priv->engine.instmem.flush(dev);
+       atomic_inc(&chan->vm->pgraph_refs);
        return 0;
 }
 
@@ -277,6 +278,8 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 
        nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
+
+       atomic_dec(&chan->vm->pgraph_refs);
 }
 
 static int
index 4ba8f74e77b18cca9141b684e8cd418f4ef6d8e2..08202fd682e4dfb4b375a79ea43f0bfd804dae32 100644 (file)
@@ -131,6 +131,7 @@ nv50_instmem_init(struct drm_device *dev)
        struct nouveau_channel *chan;
        struct nouveau_vm *vm;
        int ret, i;
+       u64 nongart_o;
        u32 tmp;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -215,37 +216,18 @@ nv50_instmem_init(struct drm_device *dev)
        for (i = 0; i < 8; i++)
                nv_wr32(dev, 0x1900 + (i*4), 0);
 
-       /* Determine VM layout */
-       dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK);
-       dev_priv->vm_gart_size = NV50_VM_BLOCK;
-
-       dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size;
-       dev_priv->vm_vram_size = dev_priv->vram_size;
-       if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM)
-               dev_priv->vm_vram_size = NV50_VM_MAX_VRAM;
-       dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK);
-       dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK;
-
-       dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size;
-
-       NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n",
-                dev_priv->vm_gart_base,
-                dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1);
-       NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n",
-                dev_priv->vm_vram_base,
-                dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1);
-
-       /* VRAM page table(s), mapped into VM at +1GiB  */
-       for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) {
-               ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8,
-                                        0, NVOBJ_FLAG_ZERO_ALLOC,
-                                        &dev_priv->vm_vram_pt[i]);
-               if (ret) {
-                       NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret);
-                       dev_priv->vm_vram_pt_nr = i;
-                       return ret;
-               }
-       }
+       /* Create shared channel VM, space is reserved for GART mappings at
+        * the beginning of this address space, it's managed separately
+        * because TTM makes life painful
+        */
+       dev_priv->vm_gart_base = 0x0020000000ULL;
+       dev_priv->vm_gart_size = 512 * 1024 * 1024;
+       nongart_o = dev_priv->vm_gart_base + dev_priv->vm_gart_size;
+
+       ret = nouveau_vm_new(dev, 0, (1ULL << 40), nongart_o,
+                            29, 12, 16, &dev_priv->chan_vm);
+       if (ret)
+               return ret;
 
        return 0;
 
@@ -269,9 +251,7 @@ nv50_instmem_takedown(struct drm_device *dev)
 
        dev_priv->ramin_available = false;
 
-       for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
-               nouveau_gpuobj_ref(NULL, &dev_priv->vm_vram_pt[i]);
-       dev_priv->vm_vram_pt_nr = 0;
+       nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL);
 
        for (i = 0x1700; i <= 0x1710; i += 4)
                nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]);
index efc63c0b0d927ecfefe0b0ea2064894cf1711386..eebab95f59b29f8cce6b8ca661fcf10a3ef7f9cf 100644 (file)
@@ -149,9 +149,24 @@ nv50_vm_flush(struct nouveau_vm *vm)
 {
        struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
        struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
+       struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
+       struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
+       struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
 
        pinstmem->flush(vm->dev);
-       nv50_vm_flush_engine(vm->dev, 6);
+
+       /* BAR */
+       if (vm != dev_priv->chan_vm) {
+               nv50_vm_flush_engine(vm->dev, 6);
+               return;
+       }
+
+       pfifo->tlb_flush(vm->dev);
+
+       if (atomic_read(&vm->pgraph_refs))
+               pgraph->tlb_flush(vm->dev);
+       if (atomic_read(&vm->pcrypt_refs))
+               pcrypt->tlb_flush(vm->dev);
 }
 
 void
index a333e5905346843c14cd2c20bddd88ff8effbcde..ec18ae1c38862088a9ecf3257003abb36da7396b 100644 (file)
@@ -53,6 +53,7 @@ nv84_crypt_create_context(struct nouveau_channel *chan)
        nv_wo32(ramin, 0xb4, 0);
 
        dev_priv->engine.instmem.flush(dev);
+       atomic_inc(&chan->vm->pcrypt_refs);
        return 0;
 }
 
@@ -80,6 +81,7 @@ nv84_crypt_destroy_context(struct nouveau_channel *chan)
        nv_wr32(dev, 0x10200c, 0x00000010);
 
        nouveau_gpuobj_ref(NULL, &chan->crypt_ctx);
+       atomic_dec(&chan->vm->pcrypt_refs);
 }
 
 void