aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-11-02 00:00:35 -0400
committerDave Airlie <airlied@redhat.com>2017-11-02 00:00:53 -0400
commit2ef7a95fe537c0e2ee039179ecab27e6d63fa1e1 (patch)
tree9ef67d24ff8e9b5242eb545237e9dddcd3463a7c /drivers/gpu
parent7a88cbd8d65d622c00bd76ba4ae1d893b292c91c (diff)
parent46bda4f4af5d061ce07148e833ff4deb50737536 (diff)
Merge branch 'linux-4.15' of git://github.com/skeggsb/linux into drm-next
- Pascal temperature sensor support - Improved BAR2 handling, greatly reduces time required to suspend - Rework of the MMU code - Allows us to properly support Pascal's new MMU layout (implemented) - Lays the groundwork for improved userspace APIs later - Misc other fixes * 'linux-4.15' of git://github.com/skeggsb/linux: (151 commits) drm/nouveau/gr/gf100-: don't prevent module load if firmware missing drm/nouveau/mmu: remove old vmm frontend drm/nouveau: improve selection of GPU page size drm/nouveau: switch over to new memory and vmm interfaces drm/nouveau: remove unused nouveau_fence_work() drm/nouveau: queue delayed unmapping of VMAs on client workqueue drm/nouveau: implement per-client delayed workqueue with fence support drm/nouveau: determine memory class for each client drm/nouveau: pass handle of vmm object to channel allocation ioctls drm/nouveau: switch to vmm limit drm/nouveau: allocate vmm object for every client drm/nouveau: replace use of cpu_coherent with memory types drm/nouveau: use nvif_mmu_type to determine BAR1 caching drm/nouveau: fetch memory type indices that we care about for ttm drm/nouveau: consolidate handling of dma mask drm/nouveau: check kind validity against mmu object drm/nouveau: allocate mmu object for every client drm/nouveau: remove trivial cases of nvxx_device() usage drm/nouveau/mmu: define user interfaces to mmu vmm opertaions drm/nouveau/mmu: define user interfaces to mmu memory allocation ...
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/Kconfig7
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl506e.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl506f.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826e.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826f.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl906f.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cla06f.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h17
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/device.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0008.h42
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if000a.h22
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if000b.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if000c.h64
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if000d.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if500b.h25
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if500d.h21
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if900b.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if900d.h21
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/ifb00d.h27
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/ifc00d.h21
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/ioctl.h10
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/mem.h18
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/mmu.h56
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/object.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/os.h14
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/vmm.h42
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/client.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/device.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/engine.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h14
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/memory.h64
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/mm.h32
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/object.h41
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/os.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h36
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h140
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c42
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c391
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.h17
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c51
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.c15
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c161
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h33
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c58
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c123
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c198
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.h30
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c54
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c280
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vmm.c135
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vmm.h31
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c12
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c9
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c43
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvif/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvif/mem.c88
-rw-r--r--drivers/gpu/drm/nouveau/nvif/mmu.c117
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c87
-rw-r--r--drivers/gpu/drm/nouveau/nvif/vmm.c167
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/memory.c99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/mm.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/object.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/oproxy.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ramht.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c98
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/falcon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c51
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c123
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c83
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/v1.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c60
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c151
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c65
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c42
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c174
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c144
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c94
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c98
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c266
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c329
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c696
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c228
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c97
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.0
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c242
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c94
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c69
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c88
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c122
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c104
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c190
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c231
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c192
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h26
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c178
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c352
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c1513
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h310
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c403
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c102
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c185
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c347
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c140
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c113
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c230
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c385
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c43
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c56
273 files changed, 10011 insertions, 3397 deletions
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild
index 2e9ce53ae3a8..9c0c650655e9 100644
--- a/drivers/gpu/drm/nouveau/Kbuild
+++ b/drivers/gpu/drm/nouveau/Kbuild
@@ -30,9 +30,11 @@ nouveau-y += nouveau_vga.o
30# DRM - memory management 30# DRM - memory management
31nouveau-y += nouveau_bo.o 31nouveau-y += nouveau_bo.o
32nouveau-y += nouveau_gem.o 32nouveau-y += nouveau_gem.o
33nouveau-y += nouveau_mem.o
33nouveau-y += nouveau_prime.o 34nouveau-y += nouveau_prime.o
34nouveau-y += nouveau_sgdma.o 35nouveau-y += nouveau_sgdma.o
35nouveau-y += nouveau_ttm.o 36nouveau-y += nouveau_ttm.o
37nouveau-y += nouveau_vmm.o
36 38
37# DRM - modesetting 39# DRM - modesetting
38nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o 40nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index c02a13406a81..4b75ad40dd80 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -56,6 +56,13 @@ config NOUVEAU_DEBUG_DEFAULT
56 help 56 help
57 Selects the default debug level 57 Selects the default debug level
58 58
59config NOUVEAU_DEBUG_MMU
60 bool "Enable additional MMU debugging"
61 depends on DRM_NOUVEAU
62 default n
63 help
64 Say Y here if you want to enable verbose MMU debug output.
65
59config DRM_NOUVEAU_BACKLIGHT 66config DRM_NOUVEAU_BACKLIGHT
60 bool "Support for backlight control" 67 bool "Support for backlight control"
61 depends on DRM_NOUVEAU 68 depends on DRM_NOUVEAU
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 5b9d549aa791..501d2d290e9c 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -48,7 +48,7 @@ nv04_display_create(struct drm_device *dev)
48 if (!disp) 48 if (!disp)
49 return -ENOMEM; 49 return -ENOMEM;
50 50
51 nvif_object_map(&drm->client.device.object); 51 nvif_object_map(&drm->client.device.object, NULL, 0);
52 52
53 nouveau_display(dev)->priv = disp; 53 nouveau_display(dev)->priv = disp;
54 nouveau_display(dev)->dtor = nv04_display_destroy; 54 nouveau_display(dev)->dtor = nv04_display_destroy;
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
index aa94b8cf9679..f50866011002 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
@@ -5,7 +5,7 @@ struct nv50_channel_dma_v0 {
5 __u8 version; 5 __u8 version;
6 __u8 chid; 6 __u8 chid;
7 __u8 pad02[6]; 7 __u8 pad02[6];
8 __u64 vm; 8 __u64 vmm;
9 __u64 pushbuf; 9 __u64 pushbuf;
10 __u64 offset; 10 __u64 offset;
11}; 11};
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
index 3b7101966de4..0e5bbb553158 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
@@ -8,6 +8,6 @@ struct nv50_channel_gpfifo_v0 {
8 __u32 ilength; 8 __u32 ilength;
9 __u64 ioffset; 9 __u64 ioffset;
10 __u64 pushbuf; 10 __u64 pushbuf;
11 __u64 vm; 11 __u64 vmm;
12}; 12};
13#endif 13#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
index 91e33db21a2f..7f6a8ce5a418 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
@@ -5,7 +5,7 @@ struct g82_channel_dma_v0 {
5 __u8 version; 5 __u8 version;
6 __u8 chid; 6 __u8 chid;
7 __u8 pad02[6]; 7 __u8 pad02[6];
8 __u64 vm; 8 __u64 vmm;
9 __u64 pushbuf; 9 __u64 pushbuf;
10 __u64 offset; 10 __u64 offset;
11}; 11};
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
index e34efd4ec537..c4d35522331a 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
@@ -8,7 +8,7 @@ struct g82_channel_gpfifo_v0 {
8 __u32 ilength; 8 __u32 ilength;
9 __u64 ioffset; 9 __u64 ioffset;
10 __u64 pushbuf; 10 __u64 pushbuf;
11 __u64 vm; 11 __u64 vmm;
12}; 12};
13 13
14#define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00 14#define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
index a2d5410a491b..169161c1587f 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
@@ -7,7 +7,7 @@ struct fermi_channel_gpfifo_v0 {
7 __u8 pad02[2]; 7 __u8 pad02[2];
8 __u32 ilength; 8 __u32 ilength;
9 __u64 ioffset; 9 __u64 ioffset;
10 __u64 vm; 10 __u64 vmm;
11}; 11};
12 12
13#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00 13#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
index 2efa3d048bb9..3e57089526e3 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
@@ -22,7 +22,7 @@ struct kepler_channel_gpfifo_a_v0 {
22 __u32 engines; 22 __u32 engines;
23 __u32 ilength; 23 __u32 ilength;
24 __u64 ioffset; 24 __u64 ioffset;
25 __u64 vm; 25 __u64 vmm;
26}; 26};
27 27
28#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00 28#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index d08da82ba7ed..56aade45067d 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -14,6 +14,23 @@
14#define NVIF_CLASS_SW_NV50 /* if0005.h */ -0x00000006 14#define NVIF_CLASS_SW_NV50 /* if0005.h */ -0x00000006
15#define NVIF_CLASS_SW_GF100 /* if0005.h */ -0x00000007 15#define NVIF_CLASS_SW_GF100 /* if0005.h */ -0x00000007
16 16
17#define NVIF_CLASS_MMU /* if0008.h */ 0x80000008
18#define NVIF_CLASS_MMU_NV04 /* if0008.h */ 0x80000009
19#define NVIF_CLASS_MMU_NV50 /* if0008.h */ 0x80005009
20#define NVIF_CLASS_MMU_GF100 /* if0008.h */ 0x80009009
21
22#define NVIF_CLASS_MEM /* if000a.h */ 0x8000000a
23#define NVIF_CLASS_MEM_NV04 /* if000b.h */ 0x8000000b
24#define NVIF_CLASS_MEM_NV50 /* if500b.h */ 0x8000500b
25#define NVIF_CLASS_MEM_GF100 /* if900b.h */ 0x8000900b
26
27#define NVIF_CLASS_VMM /* if000c.h */ 0x8000000c
28#define NVIF_CLASS_VMM_NV04 /* if000d.h */ 0x8000000d
29#define NVIF_CLASS_VMM_NV50 /* if500d.h */ 0x8000500d
30#define NVIF_CLASS_VMM_GF100 /* if900d.h */ 0x8000900d
31#define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d
32#define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d
33
17/* the below match nvidia-assigned (either in hw, or sw) class numbers */ 34/* the below match nvidia-assigned (either in hw, or sw) class numbers */
18#define NV_NULL_CLASS 0x00000030 35#define NV_NULL_CLASS 0x00000030
19 36
diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h
index bcb981711617..b579633b80c0 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/device.h
@@ -38,7 +38,6 @@ u64 nvif_device_time(struct nvif_device *);
38/*XXX*/ 38/*XXX*/
39#include <subdev/bios.h> 39#include <subdev/bios.h>
40#include <subdev/fb.h> 40#include <subdev/fb.h>
41#include <subdev/mmu.h>
42#include <subdev/bar.h> 41#include <subdev/bar.h>
43#include <subdev/gpio.h> 42#include <subdev/gpio.h>
44#include <subdev/clk.h> 43#include <subdev/clk.h>
@@ -57,8 +56,6 @@ u64 nvif_device_time(struct nvif_device *);
57}) 56})
58#define nvxx_bios(a) nvxx_device(a)->bios 57#define nvxx_bios(a) nvxx_device(a)->bios
59#define nvxx_fb(a) nvxx_device(a)->fb 58#define nvxx_fb(a) nvxx_device(a)->fb
60#define nvxx_mmu(a) nvxx_device(a)->mmu
61#define nvxx_bar(a) nvxx_device(a)->bar
62#define nvxx_gpio(a) nvxx_device(a)->gpio 59#define nvxx_gpio(a) nvxx_device(a)->gpio
63#define nvxx_clk(a) nvxx_device(a)->clk 60#define nvxx_clk(a) nvxx_device(a)->clk
64#define nvxx_i2c(a) nvxx_device(a)->i2c 61#define nvxx_i2c(a) nvxx_device(a)->i2c
@@ -66,10 +63,8 @@ u64 nvif_device_time(struct nvif_device *);
66#define nvxx_therm(a) nvxx_device(a)->therm 63#define nvxx_therm(a) nvxx_device(a)->therm
67#define nvxx_volt(a) nvxx_device(a)->volt 64#define nvxx_volt(a) nvxx_device(a)->volt
68 65
69#include <core/device.h>
70#include <engine/fifo.h> 66#include <engine/fifo.h>
71#include <engine/gr.h> 67#include <engine/gr.h>
72#include <engine/sw.h>
73 68
74#define nvxx_fifo(a) nvxx_device(a)->fifo 69#define nvxx_fifo(a) nvxx_device(a)->fifo
75#define nvxx_gr(a) nvxx_device(a)->gr 70#define nvxx_gr(a) nvxx_device(a)->gr
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0008.h b/drivers/gpu/drm/nouveau/include/nvif/if0008.h
new file mode 100644
index 000000000000..8450127420f5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0008.h
@@ -0,0 +1,42 @@
1#ifndef __NVIF_IF0008_H__
2#define __NVIF_IF0008_H__
3struct nvif_mmu_v0 {
4 __u8 version;
5 __u8 dmabits;
6 __u8 heap_nr;
7 __u8 type_nr;
8 __u16 kind_nr;
9};
10
11#define NVIF_MMU_V0_HEAP 0x00
12#define NVIF_MMU_V0_TYPE 0x01
13#define NVIF_MMU_V0_KIND 0x02
14
15struct nvif_mmu_heap_v0 {
16 __u8 version;
17 __u8 index;
18 __u8 pad02[6];
19 __u64 size;
20};
21
22struct nvif_mmu_type_v0 {
23 __u8 version;
24 __u8 index;
25 __u8 heap;
26 __u8 vram;
27 __u8 host;
28 __u8 comp;
29 __u8 disp;
30 __u8 kind;
31 __u8 mappable;
32 __u8 coherent;
33 __u8 uncached;
34};
35
36struct nvif_mmu_kind_v0 {
37 __u8 version;
38 __u8 pad01[1];
39 __u16 count;
40 __u8 data[];
41};
42#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000a.h b/drivers/gpu/drm/nouveau/include/nvif/if000a.h
new file mode 100644
index 000000000000..88d0938fbd5a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if000a.h
@@ -0,0 +1,22 @@
1#ifndef __NVIF_IF000A_H__
2#define __NVIF_IF000A_H__
3struct nvif_mem_v0 {
4 __u8 version;
5 __u8 type;
6 __u8 page;
7 __u8 pad03[5];
8 __u64 size;
9 __u64 addr;
10 __u8 data[];
11};
12
13struct nvif_mem_ram_vn {
14};
15
16struct nvif_mem_ram_v0 {
17 __u8 version;
18 __u8 pad01[7];
19 dma_addr_t *dma;
20 struct scatterlist *sgl;
21};
22#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000b.h b/drivers/gpu/drm/nouveau/include/nvif/if000b.h
new file mode 100644
index 000000000000..c677fb0293da
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if000b.h
@@ -0,0 +1,11 @@
1#ifndef __NVIF_IF000B_H__
2#define __NVIF_IF000B_H__
3#include "if000a.h"
4
5struct nv04_mem_vn {
6 /* nvkm_mem_vX ... */
7};
8
9struct nv04_mem_map_vn {
10};
11#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000c.h b/drivers/gpu/drm/nouveau/include/nvif/if000c.h
new file mode 100644
index 000000000000..2928ecd989ad
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if000c.h
@@ -0,0 +1,64 @@
1#ifndef __NVIF_IF000C_H__
2#define __NVIF_IF000C_H__
3struct nvif_vmm_v0 {
4 __u8 version;
5 __u8 page_nr;
6 __u8 pad02[6];
7 __u64 addr;
8 __u64 size;
9 __u8 data[];
10};
11
12#define NVIF_VMM_V0_PAGE 0x00
13#define NVIF_VMM_V0_GET 0x01
14#define NVIF_VMM_V0_PUT 0x02
15#define NVIF_VMM_V0_MAP 0x03
16#define NVIF_VMM_V0_UNMAP 0x04
17
18struct nvif_vmm_page_v0 {
19 __u8 version;
20 __u8 index;
21 __u8 shift;
22 __u8 sparse;
23 __u8 vram;
24 __u8 host;
25 __u8 comp;
26 __u8 pad07[1];
27};
28
29struct nvif_vmm_get_v0 {
30 __u8 version;
31#define NVIF_VMM_GET_V0_ADDR 0x00
32#define NVIF_VMM_GET_V0_PTES 0x01
33#define NVIF_VMM_GET_V0_LAZY 0x02
34 __u8 type;
35 __u8 sparse;
36 __u8 page;
37 __u8 align;
38 __u8 pad05[3];
39 __u64 size;
40 __u64 addr;
41};
42
43struct nvif_vmm_put_v0 {
44 __u8 version;
45 __u8 pad01[7];
46 __u64 addr;
47};
48
49struct nvif_vmm_map_v0 {
50 __u8 version;
51 __u8 pad01[7];
52 __u64 addr;
53 __u64 size;
54 __u64 memory;
55 __u64 offset;
56 __u8 data[];
57};
58
59struct nvif_vmm_unmap_v0 {
60 __u8 version;
61 __u8 pad01[7];
62 __u64 addr;
63};
64#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000d.h b/drivers/gpu/drm/nouveau/include/nvif/if000d.h
new file mode 100644
index 000000000000..516ec9401401
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if000d.h
@@ -0,0 +1,12 @@
1#ifndef __NVIF_IF000D_H__
2#define __NVIF_IF000D_H__
3#include "if000c.h"
4
5struct nv04_vmm_vn {
6 /* nvif_vmm_vX ... */
7};
8
9struct nv04_vmm_map_vn {
10 /* nvif_vmm_map_vX ... */
11};
12#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if500b.h b/drivers/gpu/drm/nouveau/include/nvif/if500b.h
new file mode 100644
index 000000000000..c7c8431fb2ce
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if500b.h
@@ -0,0 +1,25 @@
1#ifndef __NVIF_IF500B_H__
2#define __NVIF_IF500B_H__
3#include "if000a.h"
4
5struct nv50_mem_vn {
6 /* nvif_mem_vX ... */
7};
8
9struct nv50_mem_v0 {
10 /* nvif_mem_vX ... */
11 __u8 version;
12 __u8 bankswz;
13 __u8 contig;
14};
15
16struct nv50_mem_map_vn {
17};
18
19struct nv50_mem_map_v0 {
20 __u8 version;
21 __u8 ro;
22 __u8 kind;
23 __u8 comp;
24};
25#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if500d.h b/drivers/gpu/drm/nouveau/include/nvif/if500d.h
new file mode 100644
index 000000000000..c29a7822b363
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if500d.h
@@ -0,0 +1,21 @@
1#ifndef __NVIF_IF500D_H__
2#define __NVIF_IF500D_H__
3#include "if000c.h"
4
5struct nv50_vmm_vn {
6 /* nvif_vmm_vX ... */
7};
8
9struct nv50_vmm_map_vn {
10 /* nvif_vmm_map_vX ... */
11};
12
13struct nv50_vmm_map_v0 {
14 /* nvif_vmm_map_vX ... */
15 __u8 version;
16 __u8 ro;
17 __u8 priv;
18 __u8 kind;
19 __u8 comp;
20};
21#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if900b.h b/drivers/gpu/drm/nouveau/include/nvif/if900b.h
new file mode 100644
index 000000000000..9b164548eea8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if900b.h
@@ -0,0 +1,23 @@
1#ifndef __NVIF_IF900B_H__
2#define __NVIF_IF900B_H__
3#include "if000a.h"
4
5struct gf100_mem_vn {
6 /* nvif_mem_vX ... */
7};
8
9struct gf100_mem_v0 {
10 /* nvif_mem_vX ... */
11 __u8 version;
12 __u8 contig;
13};
14
15struct gf100_mem_map_vn {
16};
17
18struct gf100_mem_map_v0 {
19 __u8 version;
20 __u8 ro;
21 __u8 kind;
22};
23#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if900d.h b/drivers/gpu/drm/nouveau/include/nvif/if900d.h
new file mode 100644
index 000000000000..49aa50583c3d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if900d.h
@@ -0,0 +1,21 @@
1#ifndef __NVIF_IF900D_H__
2#define __NVIF_IF900D_H__
3#include "if000c.h"
4
5struct gf100_vmm_vn {
6 /* nvif_vmm_vX ... */
7};
8
9struct gf100_vmm_map_vn {
10 /* nvif_vmm_map_vX ... */
11};
12
13struct gf100_vmm_map_v0 {
14 /* nvif_vmm_map_vX ... */
15 __u8 version;
16 __u8 vol;
17 __u8 ro;
18 __u8 priv;
19 __u8 kind;
20};
21#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h b/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h
new file mode 100644
index 000000000000..a0e419830595
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h
@@ -0,0 +1,27 @@
1#ifndef __NVIF_IFB00D_H__
2#define __NVIF_IFB00D_H__
3#include "if000c.h"
4
5struct gm200_vmm_vn {
6 /* nvif_vmm_vX ... */
7};
8
9struct gm200_vmm_v0 {
10 /* nvif_vmm_vX ... */
11 __u8 version;
12 __u8 bigpage;
13};
14
15struct gm200_vmm_map_vn {
16 /* nvif_vmm_map_vX ... */
17};
18
19struct gm200_vmm_map_v0 {
20 /* nvif_vmm_map_vX ... */
21 __u8 version;
22 __u8 vol;
23 __u8 ro;
24 __u8 priv;
25 __u8 kind;
26};
27#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h b/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h
new file mode 100644
index 000000000000..1d9c637859f3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h
@@ -0,0 +1,21 @@
1#ifndef __NVIF_IFC00D_H__
2#define __NVIF_IFC00D_H__
3#include "if000c.h"
4
5struct gp100_vmm_vn {
6 /* nvif_vmm_vX ... */
7};
8
9struct gp100_vmm_map_vn {
10 /* nvif_vmm_map_vX ... */
11};
12
13struct gp100_vmm_map_v0 {
14 /* nvif_vmm_map_vX ... */
15 __u8 version;
16 __u8 vol;
17 __u8 ro;
18 __u8 priv;
19 __u8 kind;
20};
21#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
index c5f5eb83a594..1886366457f1 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
@@ -1,7 +1,7 @@
1#ifndef __NVIF_IOCTL_H__ 1#ifndef __NVIF_IOCTL_H__
2#define __NVIF_IOCTL_H__ 2#define __NVIF_IOCTL_H__
3 3
4#define NVIF_VERSION_LATEST 0x0000000000000000ULL 4#define NVIF_VERSION_LATEST 0x0000000000000100ULL
5 5
6struct nvif_ioctl_v0 { 6struct nvif_ioctl_v0 {
7 __u8 version; 7 __u8 version;
@@ -83,9 +83,13 @@ struct nvif_ioctl_wr_v0 {
83struct nvif_ioctl_map_v0 { 83struct nvif_ioctl_map_v0 {
84 /* nvif_ioctl ... */ 84 /* nvif_ioctl ... */
85 __u8 version; 85 __u8 version;
86 __u8 pad01[3]; 86#define NVIF_IOCTL_MAP_V0_IO 0x00
87 __u32 length; 87#define NVIF_IOCTL_MAP_V0_VA 0x01
88 __u8 type;
89 __u8 pad02[6];
88 __u64 handle; 90 __u64 handle;
91 __u64 length;
92 __u8 data[];
89}; 93};
90 94
91struct nvif_ioctl_unmap { 95struct nvif_ioctl_unmap {
diff --git a/drivers/gpu/drm/nouveau/include/nvif/mem.h b/drivers/gpu/drm/nouveau/include/nvif/mem.h
new file mode 100644
index 000000000000..b542fe38398e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/mem.h
@@ -0,0 +1,18 @@
1#ifndef __NVIF_MEM_H__
2#define __NVIF_MEM_H__
3#include "mmu.h"
4
5struct nvif_mem {
6 struct nvif_object object;
7 u8 type;
8 u8 page;
9 u64 addr;
10 u64 size;
11};
12
13int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page,
14 u64 size, void *argv, u32 argc, struct nvif_mem *);
15int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page,
16 u64 size, void *argv, u32 argc, struct nvif_mem *);
17void nvif_mem_fini(struct nvif_mem *);
18#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/mmu.h b/drivers/gpu/drm/nouveau/include/nvif/mmu.h
new file mode 100644
index 000000000000..c8cd5b5b0688
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/mmu.h
@@ -0,0 +1,56 @@
1#ifndef __NVIF_MMU_H__
2#define __NVIF_MMU_H__
3#include <nvif/object.h>
4
5struct nvif_mmu {
6 struct nvif_object object;
7 u8 dmabits;
8 u8 heap_nr;
9 u8 type_nr;
10 u16 kind_nr;
11
12 struct {
13 u64 size;
14 } *heap;
15
16 struct {
17#define NVIF_MEM_VRAM 0x01
18#define NVIF_MEM_HOST 0x02
19#define NVIF_MEM_COMP 0x04
20#define NVIF_MEM_DISP 0x08
21#define NVIF_MEM_KIND 0x10
22#define NVIF_MEM_MAPPABLE 0x20
23#define NVIF_MEM_COHERENT 0x40
24#define NVIF_MEM_UNCACHED 0x80
25 u8 type;
26 u8 heap;
27 } *type;
28
29 u8 *kind;
30};
31
32int nvif_mmu_init(struct nvif_object *, s32 oclass, struct nvif_mmu *);
33void nvif_mmu_fini(struct nvif_mmu *);
34
35static inline bool
36nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind)
37{
38 const u8 invalid = mmu->kind_nr - 1;
39 if (kind) {
40 if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid)
41 return false;
42 }
43 return true;
44}
45
46static inline int
47nvif_mmu_type(struct nvif_mmu *mmu, u8 mask)
48{
49 int i;
50 for (i = 0; i < mmu->type_nr; i++) {
51 if ((mmu->type[i].type & mask) == mask)
52 return i;
53 }
54 return -EINVAL;
55}
56#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h
index 9e58b305b020..0b54261bdefe 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/object.h
@@ -16,7 +16,7 @@ struct nvif_object {
16 void *priv; /*XXX: hack */ 16 void *priv; /*XXX: hack */
17 struct { 17 struct {
18 void __iomem *ptr; 18 void __iomem *ptr;
19 u32 size; 19 u64 size;
20 } map; 20 } map;
21}; 21};
22 22
@@ -29,7 +29,10 @@ void nvif_object_sclass_put(struct nvif_sclass **);
29u32 nvif_object_rd(struct nvif_object *, int, u64); 29u32 nvif_object_rd(struct nvif_object *, int, u64);
30void nvif_object_wr(struct nvif_object *, int, u64, u32); 30void nvif_object_wr(struct nvif_object *, int, u64, u32);
31int nvif_object_mthd(struct nvif_object *, u32, void *, u32); 31int nvif_object_mthd(struct nvif_object *, u32, void *, u32);
32int nvif_object_map(struct nvif_object *); 32int nvif_object_map_handle(struct nvif_object *, void *, u32,
33 u64 *handle, u64 *length);
34void nvif_object_unmap_handle(struct nvif_object *);
35int nvif_object_map(struct nvif_object *, void *, u32);
33void nvif_object_unmap(struct nvif_object *); 36void nvif_object_unmap(struct nvif_object *);
34 37
35#define nvif_handle(a) (unsigned long)(void *)(a) 38#define nvif_handle(a) (unsigned long)(void *)(a)
diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h
index 9fcab67c8557..5efdf80d5abc 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/os.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/os.h
@@ -33,18 +33,4 @@
33 33
34#include <soc/tegra/fuse.h> 34#include <soc/tegra/fuse.h>
35#include <soc/tegra/pmc.h> 35#include <soc/tegra/pmc.h>
36
37#ifndef ioread32_native
38#ifdef __BIG_ENDIAN
39#define ioread16_native ioread16be
40#define iowrite16_native iowrite16be
41#define ioread32_native ioread32be
42#define iowrite32_native iowrite32be
43#else /* def __BIG_ENDIAN */
44#define ioread16_native ioread16
45#define iowrite16_native iowrite16
46#define ioread32_native ioread32
47#define iowrite32_native iowrite32
48#endif /* def __BIG_ENDIAN else */
49#endif /* !ioread32_native */
50#endif 36#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/vmm.h b/drivers/gpu/drm/nouveau/include/nvif/vmm.h
new file mode 100644
index 000000000000..c5db8a2e82df
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/vmm.h
@@ -0,0 +1,42 @@
1#ifndef __NVIF_VMM_H__
2#define __NVIF_VMM_H__
3#include <nvif/object.h>
4struct nvif_mem;
5struct nvif_mmu;
6
7enum nvif_vmm_get {
8 ADDR,
9 PTES,
10 LAZY
11};
12
13struct nvif_vma {
14 u64 addr;
15 u64 size;
16};
17
18struct nvif_vmm {
19 struct nvif_object object;
20 u64 start;
21 u64 limit;
22
23 struct {
24 u8 shift;
25 bool sparse:1;
26 bool vram:1;
27 bool host:1;
28 bool comp:1;
29 } *page;
30 int page_nr;
31};
32
33int nvif_vmm_init(struct nvif_mmu *, s32 oclass, u64 addr, u64 size,
34 void *argv, u32 argc, struct nvif_vmm *);
35void nvif_vmm_fini(struct nvif_vmm *);
36int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse,
37 u8 page, u8 align, u64 size, struct nvif_vma *);
38void nvif_vmm_put(struct nvif_vmm *, struct nvif_vma *);
39int nvif_vmm_map(struct nvif_vmm *, u64 addr, u64 size, void *argv, u32 argc,
40 struct nvif_mem *, u64 offset);
41int nvif_vmm_unmap(struct nvif_vmm *, u64);
42#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
index e876634da10a..79624f6d0a2b 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
@@ -16,7 +16,8 @@ struct nvkm_client {
16 void *data; 16 void *data;
17 int (*ntfy)(const void *, u32, const void *, u32); 17 int (*ntfy)(const void *, u32, const void *, u32);
18 18
19 struct nvkm_vm *vm; 19 struct list_head umem;
20 spinlock_t lock;
20}; 21};
21 22
22int nvkm_client_new(const char *name, u64 device, const char *cfg, 23int nvkm_client_new(const char *name, u64 device, const char *cfg,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index bb4c214f1046..5046e1db99ac 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -1,7 +1,7 @@
1#ifndef __NVKM_DEVICE_H__ 1#ifndef __NVKM_DEVICE_H__
2#define __NVKM_DEVICE_H__ 2#define __NVKM_DEVICE_H__
3#include <core/oclass.h>
3#include <core/event.h> 4#include <core/event.h>
4#include <core/object.h>
5 5
6enum nvkm_devidx { 6enum nvkm_devidx {
7 NVKM_SUBDEV_PCI, 7 NVKM_SUBDEV_PCI,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
index d4cd2fbfde88..7730499bfd95 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
@@ -15,6 +15,7 @@ struct nvkm_engine {
15 15
16struct nvkm_engine_func { 16struct nvkm_engine_func {
17 void *(*dtor)(struct nvkm_engine *); 17 void *(*dtor)(struct nvkm_engine *);
18 void (*preinit)(struct nvkm_engine *);
18 int (*oneinit)(struct nvkm_engine *); 19 int (*oneinit)(struct nvkm_engine *);
19 int (*init)(struct nvkm_engine *); 20 int (*init)(struct nvkm_engine *);
20 int (*fini)(struct nvkm_engine *, bool suspend); 21 int (*fini)(struct nvkm_engine *, bool suspend);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
index c23da4f05929..51691667b813 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h
@@ -1,17 +1,16 @@
1#ifndef __NVKM_GPUOBJ_H__ 1#ifndef __NVKM_GPUOBJ_H__
2#define __NVKM_GPUOBJ_H__ 2#define __NVKM_GPUOBJ_H__
3#include <core/object.h>
4#include <core/memory.h> 3#include <core/memory.h>
5#include <core/mm.h> 4#include <core/mm.h>
6struct nvkm_vma;
7struct nvkm_vm;
8 5
9#define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 6#define NVOBJ_FLAG_ZERO_ALLOC 0x00000001
10#define NVOBJ_FLAG_HEAP 0x00000004 7#define NVOBJ_FLAG_HEAP 0x00000004
11 8
12struct nvkm_gpuobj { 9struct nvkm_gpuobj {
13 struct nvkm_object object; 10 union {
14 const struct nvkm_gpuobj_func *func; 11 const struct nvkm_gpuobj_func *func;
12 const struct nvkm_gpuobj_func *ptrs;
13 };
15 struct nvkm_gpuobj *parent; 14 struct nvkm_gpuobj *parent;
16 struct nvkm_memory *memory; 15 struct nvkm_memory *memory;
17 struct nvkm_mm_node *node; 16 struct nvkm_mm_node *node;
@@ -28,15 +27,14 @@ struct nvkm_gpuobj_func {
28 void (*release)(struct nvkm_gpuobj *); 27 void (*release)(struct nvkm_gpuobj *);
29 u32 (*rd32)(struct nvkm_gpuobj *, u32 offset); 28 u32 (*rd32)(struct nvkm_gpuobj *, u32 offset);
30 void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data); 29 void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data);
30 int (*map)(struct nvkm_gpuobj *, u64 offset, struct nvkm_vmm *,
31 struct nvkm_vma *, void *argv, u32 argc);
31}; 32};
32 33
33int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, 34int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero,
34 struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); 35 struct nvkm_gpuobj *parent, struct nvkm_gpuobj **);
35void nvkm_gpuobj_del(struct nvkm_gpuobj **); 36void nvkm_gpuobj_del(struct nvkm_gpuobj **);
36int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); 37int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **);
37int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access,
38 struct nvkm_vma *);
39void nvkm_gpuobj_unmap(struct nvkm_vma *);
40void nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src, 38void nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src,
41 u32 length); 39 u32 length);
42void nvkm_gpuobj_memcpy_from(void *dst, struct nvkm_gpuobj *src, u32 srcoffset, 40void nvkm_gpuobj_memcpy_from(void *dst, struct nvkm_gpuobj *src, u32 srcoffset,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
index 33ca6769266a..13ebf4da2b96 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
@@ -3,7 +3,12 @@
3#include <core/os.h> 3#include <core/os.h>
4struct nvkm_device; 4struct nvkm_device;
5struct nvkm_vma; 5struct nvkm_vma;
6struct nvkm_vm; 6struct nvkm_vmm;
7
8struct nvkm_tags {
9 struct nvkm_mm_node *mn;
10 refcount_t refcount;
11};
7 12
8enum nvkm_memory_target { 13enum nvkm_memory_target {
9 NVKM_MEM_TARGET_INST, /* instance memory */ 14 NVKM_MEM_TARGET_INST, /* instance memory */
@@ -14,41 +19,84 @@ enum nvkm_memory_target {
14 19
15struct nvkm_memory { 20struct nvkm_memory {
16 const struct nvkm_memory_func *func; 21 const struct nvkm_memory_func *func;
22 const struct nvkm_memory_ptrs *ptrs;
23 struct kref kref;
24 struct nvkm_tags *tags;
17}; 25};
18 26
19struct nvkm_memory_func { 27struct nvkm_memory_func {
20 void *(*dtor)(struct nvkm_memory *); 28 void *(*dtor)(struct nvkm_memory *);
21 enum nvkm_memory_target (*target)(struct nvkm_memory *); 29 enum nvkm_memory_target (*target)(struct nvkm_memory *);
30 u8 (*page)(struct nvkm_memory *);
22 u64 (*addr)(struct nvkm_memory *); 31 u64 (*addr)(struct nvkm_memory *);
23 u64 (*size)(struct nvkm_memory *); 32 u64 (*size)(struct nvkm_memory *);
24 void (*boot)(struct nvkm_memory *, struct nvkm_vm *); 33 void (*boot)(struct nvkm_memory *, struct nvkm_vmm *);
25 void __iomem *(*acquire)(struct nvkm_memory *); 34 void __iomem *(*acquire)(struct nvkm_memory *);
26 void (*release)(struct nvkm_memory *); 35 void (*release)(struct nvkm_memory *);
36 int (*map)(struct nvkm_memory *, u64 offset, struct nvkm_vmm *,
37 struct nvkm_vma *, void *argv, u32 argc);
38};
39
40struct nvkm_memory_ptrs {
27 u32 (*rd32)(struct nvkm_memory *, u64 offset); 41 u32 (*rd32)(struct nvkm_memory *, u64 offset);
28 void (*wr32)(struct nvkm_memory *, u64 offset, u32 data); 42 void (*wr32)(struct nvkm_memory *, u64 offset, u32 data);
29 void (*map)(struct nvkm_memory *, struct nvkm_vma *, u64 offset);
30}; 43};
31 44
32void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *); 45void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *);
33int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target, 46int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target,
34 u64 size, u32 align, bool zero, struct nvkm_memory **); 47 u64 size, u32 align, bool zero, struct nvkm_memory **);
35void nvkm_memory_del(struct nvkm_memory **); 48struct nvkm_memory *nvkm_memory_ref(struct nvkm_memory *);
49void nvkm_memory_unref(struct nvkm_memory **);
50int nvkm_memory_tags_get(struct nvkm_memory *, struct nvkm_device *, u32 tags,
51 void (*clear)(struct nvkm_device *, u32, u32),
52 struct nvkm_tags **);
53void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *,
54 struct nvkm_tags **);
55
36#define nvkm_memory_target(p) (p)->func->target(p) 56#define nvkm_memory_target(p) (p)->func->target(p)
57#define nvkm_memory_page(p) (p)->func->page(p)
37#define nvkm_memory_addr(p) (p)->func->addr(p) 58#define nvkm_memory_addr(p) (p)->func->addr(p)
38#define nvkm_memory_size(p) (p)->func->size(p) 59#define nvkm_memory_size(p) (p)->func->size(p)
39#define nvkm_memory_boot(p,v) (p)->func->boot((p),(v)) 60#define nvkm_memory_boot(p,v) (p)->func->boot((p),(v))
40#define nvkm_memory_map(p,v,o) (p)->func->map((p),(v),(o)) 61#define nvkm_memory_map(p,o,vm,va,av,ac) \
62 (p)->func->map((p),(o),(vm),(va),(av),(ac))
41 63
42/* accessor macros - kmap()/done() must bracket use of the other accessor 64/* accessor macros - kmap()/done() must bracket use of the other accessor
43 * macros to guarantee correct behaviour across all chipsets 65 * macros to guarantee correct behaviour across all chipsets
44 */ 66 */
45#define nvkm_kmap(o) (o)->func->acquire(o) 67#define nvkm_kmap(o) (o)->func->acquire(o)
46#define nvkm_ro32(o,a) (o)->func->rd32((o), (a)) 68#define nvkm_done(o) (o)->func->release(o)
47#define nvkm_wo32(o,a,d) (o)->func->wr32((o), (a), (d)) 69
70#define nvkm_ro32(o,a) (o)->ptrs->rd32((o), (a))
71#define nvkm_wo32(o,a,d) (o)->ptrs->wr32((o), (a), (d))
48#define nvkm_mo32(o,a,m,d) ({ \ 72#define nvkm_mo32(o,a,m,d) ({ \
49 u32 _addr = (a), _data = nvkm_ro32((o), _addr); \ 73 u32 _addr = (a), _data = nvkm_ro32((o), _addr); \
50 nvkm_wo32((o), _addr, (_data & ~(m)) | (d)); \ 74 nvkm_wo32((o), _addr, (_data & ~(m)) | (d)); \
51 _data; \ 75 _data; \
52}) 76})
53#define nvkm_done(o) (o)->func->release(o) 77
78#define nvkm_wo64(o,a,d) do { \
79 u64 __a = (a), __d = (d); \
80 nvkm_wo32((o), __a + 0, lower_32_bits(__d)); \
81 nvkm_wo32((o), __a + 4, upper_32_bits(__d)); \
82} while(0)
83
84#define nvkm_fill(t,s,o,a,d,c) do { \
85 u64 _a = (a), _c = (c), _d = (d), _o = _a >> s, _s = _c << s; \
86 u##t __iomem *_m = nvkm_kmap(o); \
87 if (likely(_m)) { \
88 if (_d) { \
89 while (_c--) \
90 iowrite##t##_native(_d, &_m[_o++]); \
91 } else { \
92 memset_io(&_m[_o], _d, _s); \
93 } \
94 } else { \
95 for (; _c; _c--, _a += BIT(s)) \
96 nvkm_wo##t((o), _a, _d); \
97 } \
98 nvkm_done(o); \
99} while(0)
100#define nvkm_fo32(o,a,d,c) nvkm_fill(32, 2, (o), (a), (d), (c))
101#define nvkm_fo64(o,a,d,c) nvkm_fill(64, 3, (o), (a), (d), (c))
54#endif 102#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
index 7bd4897a8a2a..5c1261351138 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h
@@ -30,7 +30,7 @@ nvkm_mm_initialised(struct nvkm_mm *mm)
30 return mm->heap_nodes; 30 return mm->heap_nodes;
31} 31}
32 32
33int nvkm_mm_init(struct nvkm_mm *, u32 offset, u32 length, u32 block); 33int nvkm_mm_init(struct nvkm_mm *, u8 heap, u32 offset, u32 length, u32 block);
34int nvkm_mm_fini(struct nvkm_mm *); 34int nvkm_mm_fini(struct nvkm_mm *);
35int nvkm_mm_head(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, 35int nvkm_mm_head(struct nvkm_mm *, u8 heap, u8 type, u32 size_max,
36 u32 size_min, u32 align, struct nvkm_mm_node **); 36 u32 size_min, u32 align, struct nvkm_mm_node **);
@@ -39,9 +39,39 @@ int nvkm_mm_tail(struct nvkm_mm *, u8 heap, u8 type, u32 size_max,
39void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **); 39void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **);
40void nvkm_mm_dump(struct nvkm_mm *, const char *); 40void nvkm_mm_dump(struct nvkm_mm *, const char *);
41 41
42static inline u32
43nvkm_mm_heap_size(struct nvkm_mm *mm, u8 heap)
44{
45 struct nvkm_mm_node *node;
46 u32 size = 0;
47 list_for_each_entry(node, &mm->nodes, nl_entry) {
48 if (node->heap == heap)
49 size += node->length;
50 }
51 return size;
52}
53
42static inline bool 54static inline bool
43nvkm_mm_contiguous(struct nvkm_mm_node *node) 55nvkm_mm_contiguous(struct nvkm_mm_node *node)
44{ 56{
45 return !node->next; 57 return !node->next;
46} 58}
59
60static inline u32
61nvkm_mm_addr(struct nvkm_mm_node *node)
62{
63 if (WARN_ON(!nvkm_mm_contiguous(node)))
64 return 0;
65 return node->offset;
66}
67
68static inline u32
69nvkm_mm_size(struct nvkm_mm_node *node)
70{
71 u32 size = 0;
72 do {
73 size += node->length;
74 } while ((node = node->next));
75 return size;
76}
47#endif 77#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
index 96dda350ada3..916a4b76d430 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
@@ -1,10 +1,8 @@
1#ifndef __NVKM_OBJECT_H__ 1#ifndef __NVKM_OBJECT_H__
2#define __NVKM_OBJECT_H__ 2#define __NVKM_OBJECT_H__
3#include <core/os.h> 3#include <core/oclass.h>
4#include <core/debug.h>
5struct nvkm_event; 4struct nvkm_event;
6struct nvkm_gpuobj; 5struct nvkm_gpuobj;
7struct nvkm_oclass;
8 6
9struct nvkm_object { 7struct nvkm_object {
10 const struct nvkm_object_func *func; 8 const struct nvkm_object_func *func;
@@ -21,13 +19,20 @@ struct nvkm_object {
21 struct rb_node node; 19 struct rb_node node;
22}; 20};
23 21
22enum nvkm_object_map {
23 NVKM_OBJECT_MAP_IO,
24 NVKM_OBJECT_MAP_VA
25};
26
24struct nvkm_object_func { 27struct nvkm_object_func {
25 void *(*dtor)(struct nvkm_object *); 28 void *(*dtor)(struct nvkm_object *);
26 int (*init)(struct nvkm_object *); 29 int (*init)(struct nvkm_object *);
27 int (*fini)(struct nvkm_object *, bool suspend); 30 int (*fini)(struct nvkm_object *, bool suspend);
28 int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size); 31 int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size);
29 int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **); 32 int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **);
30 int (*map)(struct nvkm_object *, u64 *addr, u32 *size); 33 int (*map)(struct nvkm_object *, void *argv, u32 argc,
34 enum nvkm_object_map *, u64 *addr, u64 *size);
35 int (*unmap)(struct nvkm_object *);
31 int (*rd08)(struct nvkm_object *, u64 addr, u8 *data); 36 int (*rd08)(struct nvkm_object *, u64 addr, u8 *data);
32 int (*rd16)(struct nvkm_object *, u64 addr, u16 *data); 37 int (*rd16)(struct nvkm_object *, u64 addr, u16 *data);
33 int (*rd32)(struct nvkm_object *, u64 addr, u32 *data); 38 int (*rd32)(struct nvkm_object *, u64 addr, u32 *data);
@@ -52,7 +57,9 @@ int nvkm_object_init(struct nvkm_object *);
52int nvkm_object_fini(struct nvkm_object *, bool suspend); 57int nvkm_object_fini(struct nvkm_object *, bool suspend);
53int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); 58int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size);
54int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); 59int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **);
55int nvkm_object_map(struct nvkm_object *, u64 *addr, u32 *size); 60int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc,
61 enum nvkm_object_map *, u64 *addr, u64 *size);
62int nvkm_object_unmap(struct nvkm_object *);
56int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); 63int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data);
57int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); 64int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data);
58int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); 65int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data);
@@ -66,28 +73,4 @@ bool nvkm_object_insert(struct nvkm_object *);
66void nvkm_object_remove(struct nvkm_object *); 73void nvkm_object_remove(struct nvkm_object *);
67struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object, 74struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object,
68 const struct nvkm_object_func *); 75 const struct nvkm_object_func *);
69
70struct nvkm_sclass {
71 int minver;
72 int maxver;
73 s32 oclass;
74 const struct nvkm_object_func *func;
75 int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
76 struct nvkm_object **);
77};
78
79struct nvkm_oclass {
80 int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
81 struct nvkm_object **);
82 struct nvkm_sclass base;
83 const void *priv;
84 const void *engn;
85 u32 handle;
86 u8 route;
87 u64 token;
88 u64 object;
89 struct nvkm_client *client;
90 struct nvkm_object *parent;
91 struct nvkm_engine *engine;
92};
93#endif 76#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h
new file mode 100644
index 000000000000..8e1b945d38f3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h
@@ -0,0 +1,31 @@
1#ifndef __NVKM_OCLASS_H__
2#define __NVKM_OCLASS_H__
3#include <core/os.h>
4#include <core/debug.h>
5struct nvkm_oclass;
6struct nvkm_object;
7
8struct nvkm_sclass {
9 int minver;
10 int maxver;
11 s32 oclass;
12 const struct nvkm_object_func *func;
13 int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
14 struct nvkm_object **);
15};
16
17struct nvkm_oclass {
18 int (*ctor)(const struct nvkm_oclass *, void *data, u32 size,
19 struct nvkm_object **);
20 struct nvkm_sclass base;
21 const void *priv;
22 const void *engn;
23 u32 handle;
24 u8 route;
25 u64 token;
26 u64 object;
27 struct nvkm_client *client;
28 struct nvkm_object *parent;
29 struct nvkm_engine *engine;
30};
31#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
index cd57e238ddd3..1f0108fdd24a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
@@ -1,4 +1,23 @@
1#ifndef __NVKM_OS_H__ 1#ifndef __NVKM_OS_H__
2#define __NVKM_OS_H__ 2#define __NVKM_OS_H__
3#include <nvif/os.h> 3#include <nvif/os.h>
4
5#ifdef __BIG_ENDIAN
6#define ioread16_native ioread16be
7#define iowrite16_native iowrite16be
8#define ioread32_native ioread32be
9#define iowrite32_native iowrite32be
10#else
11#define ioread16_native ioread16
12#define iowrite16_native iowrite16
13#define ioread32_native ioread32
14#define iowrite32_native iowrite32
15#endif
16
17#define iowrite64_native(v,p) do { \
18 u32 __iomem *_p = (u32 __iomem *)(p); \
19 u64 _v = (v); \
20 iowrite32_native(lower_32_bits(_v), &_p[0]); \
21 iowrite32_native(upper_32_bits(_v), &_p[1]); \
22} while(0)
4#endif 23#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
index 5ee6298991e2..8a48ca67f60d 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h
@@ -1,6 +1,7 @@
1#ifndef __NVKM_RAMHT_H__ 1#ifndef __NVKM_RAMHT_H__
2#define __NVKM_RAMHT_H__ 2#define __NVKM_RAMHT_H__
3#include <core/gpuobj.h> 3#include <core/gpuobj.h>
4struct nvkm_object;
4 5
5struct nvkm_ramht_data { 6struct nvkm_ramht_data {
6 struct nvkm_gpuobj *inst; 7 struct nvkm_gpuobj *inst;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
index ca9ed3d68f44..a6c21be7537f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
@@ -33,7 +33,7 @@ void nvkm_subdev_intr(struct nvkm_subdev *);
33/* subdev logging */ 33/* subdev logging */
34#define nvkm_printk_(s,l,p,f,a...) do { \ 34#define nvkm_printk_(s,l,p,f,a...) do { \
35 const struct nvkm_subdev *_subdev = (s); \ 35 const struct nvkm_subdev *_subdev = (s); \
36 if (_subdev->debug >= (l)) { \ 36 if (CONFIG_NOUVEAU_DEBUG >= (l) && _subdev->debug >= (l)) { \
37 dev_##p(_subdev->device->dev, "%s: "f, \ 37 dev_##p(_subdev->device->dev, "%s: "f, \
38 nvkm_subdev_name[_subdev->index], ##a); \ 38 nvkm_subdev_name[_subdev->index], ##a); \
39 } \ 39 } \
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
index d2a6532ce3b9..b672a3b07f55 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h
@@ -1,6 +1,7 @@
1#ifndef __NVKM_DMA_H__ 1#ifndef __NVKM_DMA_H__
2#define __NVKM_DMA_H__ 2#define __NVKM_DMA_H__
3#include <core/engine.h> 3#include <core/engine.h>
4#include <core/object.h>
4struct nvkm_client; 5struct nvkm_client;
5 6
6struct nvkm_dmaobj { 7struct nvkm_dmaobj {
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
index e1a854e2ade1..f0024fb5a5af 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
@@ -3,6 +3,7 @@
3#define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine) 3#define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine)
4#include <core/engine.h> 4#include <core/engine.h>
5struct nvkm_fifo_chan; 5struct nvkm_fifo_chan;
6struct nvkm_gpuobj;
6 7
7enum nvkm_falcon_dmaidx { 8enum nvkm_falcon_dmaidx {
8 FALCON_DMAIDX_UCODE = 0, 9 FALCON_DMAIDX_UCODE = 0,
@@ -77,7 +78,7 @@ struct nvkm_falcon_func {
77 void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); 78 void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool);
78 void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); 79 void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8);
79 void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); 80 void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *);
80 void (*bind_context)(struct nvkm_falcon *, struct nvkm_gpuobj *); 81 void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *);
81 int (*wait_for_halt)(struct nvkm_falcon *, u32); 82 int (*wait_for_halt)(struct nvkm_falcon *, u32);
82 int (*clear_interrupt)(struct nvkm_falcon *, u32); 83 int (*clear_interrupt)(struct nvkm_falcon *, u32);
83 void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); 84 void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr);
@@ -112,7 +113,7 @@ void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8,
112 bool); 113 bool);
113void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); 114void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
114void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); 115void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
115void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *); 116void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
116void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); 117void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32);
117void nvkm_falcon_start(struct nvkm_falcon *); 118void nvkm_falcon_start(struct nvkm_falcon *);
118int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); 119int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
index f00527b36acc..e42d686fbd8b 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
@@ -1,6 +1,7 @@
1#ifndef __NVKM_FIFO_H__ 1#ifndef __NVKM_FIFO_H__
2#define __NVKM_FIFO_H__ 2#define __NVKM_FIFO_H__
3#include <core/engine.h> 3#include <core/engine.h>
4#include <core/object.h>
4#include <core/event.h> 5#include <core/event.h>
5 6
6#define NVKM_FIFO_CHID_NR 4096 7#define NVKM_FIFO_CHID_NR 4096
@@ -21,7 +22,7 @@ struct nvkm_fifo_chan {
21 u16 chid; 22 u16 chid;
22 struct nvkm_gpuobj *inst; 23 struct nvkm_gpuobj *inst;
23 struct nvkm_gpuobj *push; 24 struct nvkm_gpuobj *push;
24 struct nvkm_vm *vm; 25 struct nvkm_vmm *vmm;
25 void __iomem *user; 26 void __iomem *user;
26 u64 addr; 27 u64 addr;
27 u32 size; 28 u32 size;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
index d3071b5a4f98..ffa963939e15 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h
@@ -8,17 +8,22 @@ struct nvkm_bar {
8 struct nvkm_subdev subdev; 8 struct nvkm_subdev subdev;
9 9
10 spinlock_t lock; 10 spinlock_t lock;
11 bool bar2;
11 12
12 /* whether the BAR supports to be ioremapped WC or should be uncached */ 13 /* whether the BAR supports to be ioremapped WC or should be uncached */
13 bool iomap_uncached; 14 bool iomap_uncached;
14}; 15};
15 16
17struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *);
18void nvkm_bar_bar2_init(struct nvkm_device *);
19void nvkm_bar_bar2_fini(struct nvkm_device *);
20struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *);
16void nvkm_bar_flush(struct nvkm_bar *); 21void nvkm_bar_flush(struct nvkm_bar *);
17struct nvkm_vm *nvkm_bar_kmap(struct nvkm_bar *);
18int nvkm_bar_umap(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *);
19 22
20int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 23int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
21int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 24int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
22int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 25int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
23int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); 26int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
27int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
28int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
24#endif 29#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
index 28d513fbf44c..a00fd2e59215 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
@@ -1,8 +1,7 @@
1#ifndef __NVKM_FB_H__ 1#ifndef __NVKM_FB_H__
2#define __NVKM_FB_H__ 2#define __NVKM_FB_H__
3#include <core/subdev.h> 3#include <core/subdev.h>
4 4#include <core/mm.h>
5#include <subdev/mmu.h>
6 5
7/* memory type/access flags, do not match hardware values */ 6/* memory type/access flags, do not match hardware values */
8#define NV_MEM_ACCESS_RO 1 7#define NV_MEM_ACCESS_RO 1
@@ -21,22 +20,6 @@
21#define NVKM_RAM_TYPE_VM 0x7f 20#define NVKM_RAM_TYPE_VM 0x7f
22#define NV_MEM_COMP_VM 0x03 21#define NV_MEM_COMP_VM 0x03
23 22
24struct nvkm_mem {
25 struct drm_device *dev;
26
27 struct nvkm_vma bar_vma;
28 struct nvkm_vma vma[2];
29 u8 page_shift;
30
31 struct nvkm_mm_node *tag;
32 struct nvkm_mm_node *mem;
33 dma_addr_t *pages;
34 u32 memtype;
35 u64 offset;
36 u64 size;
37 struct sg_table *sg;
38};
39
40struct nvkm_fb_tile { 23struct nvkm_fb_tile {
41 struct nvkm_mm_node *tag; 24 struct nvkm_mm_node *tag;
42 u32 addr; 25 u32 addr;
@@ -50,6 +33,7 @@ struct nvkm_fb {
50 struct nvkm_subdev subdev; 33 struct nvkm_subdev subdev;
51 34
52 struct nvkm_ram *ram; 35 struct nvkm_ram *ram;
36 struct nvkm_mm tags;
53 37
54 struct { 38 struct {
55 struct nvkm_fb_tile region[16]; 39 struct nvkm_fb_tile region[16];
@@ -62,7 +46,6 @@ struct nvkm_fb {
62 struct nvkm_memory *mmu_wr; 46 struct nvkm_memory *mmu_wr;
63}; 47};
64 48
65bool nvkm_fb_memtype_valid(struct nvkm_fb *, u32 memtype);
66void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size, 49void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size,
67 u32 pitch, u32 flags, struct nvkm_fb_tile *); 50 u32 pitch, u32 flags, struct nvkm_fb_tile *);
68void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *); 51void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *);
@@ -129,8 +112,11 @@ struct nvkm_ram {
129 u64 size; 112 u64 size;
130 113
131#define NVKM_RAM_MM_SHIFT 12 114#define NVKM_RAM_MM_SHIFT 12
115#define NVKM_RAM_MM_ANY (NVKM_MM_HEAP_ANY + 0)
116#define NVKM_RAM_MM_NORMAL (NVKM_MM_HEAP_ANY + 1)
117#define NVKM_RAM_MM_NOMAP (NVKM_MM_HEAP_ANY + 2)
118#define NVKM_RAM_MM_MIXED (NVKM_MM_HEAP_ANY + 3)
132 struct nvkm_mm vram; 119 struct nvkm_mm vram;
133 struct nvkm_mm tags;
134 u64 stolen; 120 u64 stolen;
135 121
136 int ranks; 122 int ranks;
@@ -147,6 +133,10 @@ struct nvkm_ram {
147 struct nvkm_ram_data target; 133 struct nvkm_ram_data target;
148}; 134};
149 135
136int
137nvkm_ram_get(struct nvkm_device *, u8 heap, u8 type, u8 page, u64 size,
138 bool contig, bool back, struct nvkm_memory **);
139
150struct nvkm_ram_func { 140struct nvkm_ram_func {
151 u64 upper; 141 u64 upper;
152 u32 (*probe_fbp)(const struct nvkm_ram_func *, struct nvkm_device *, 142 u32 (*probe_fbp)(const struct nvkm_ram_func *, struct nvkm_device *,
@@ -157,14 +147,8 @@ struct nvkm_ram_func {
157 void *(*dtor)(struct nvkm_ram *); 147 void *(*dtor)(struct nvkm_ram *);
158 int (*init)(struct nvkm_ram *); 148 int (*init)(struct nvkm_ram *);
159 149
160 int (*get)(struct nvkm_ram *, u64 size, u32 align, u32 size_nc,
161 u32 type, struct nvkm_mem **);
162 void (*put)(struct nvkm_ram *, struct nvkm_mem **);
163
164 int (*calc)(struct nvkm_ram *, u32 freq); 150 int (*calc)(struct nvkm_ram *, u32 freq);
165 int (*prog)(struct nvkm_ram *); 151 int (*prog)(struct nvkm_ram *);
166 void (*tidy)(struct nvkm_ram *); 152 void (*tidy)(struct nvkm_ram *);
167}; 153};
168
169extern const u8 gf100_pte_storage_type_map[256];
170#endif 154#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
index 40f845e31272..8111c0c3c5ec 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
@@ -9,6 +9,7 @@ struct nvkm_instmem {
9 9
10 spinlock_t lock; 10 spinlock_t lock;
11 struct list_head list; 11 struct list_head list;
12 struct list_head boot;
12 u32 reserved; 13 u32 reserved;
13 14
14 struct nvkm_memory *vbios; 15 struct nvkm_memory *vbios;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
index cd755baf9cab..4a224fd22e48 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
@@ -14,8 +14,7 @@ struct nvkm_ltc {
14 14
15 u32 num_tags; 15 u32 num_tags;
16 u32 tag_base; 16 u32 tag_base;
17 struct nvkm_mm tags; 17 struct nvkm_memory *tag_ram;
18 struct nvkm_mm_node *tag_ram;
19 18
20 int zbc_min; 19 int zbc_min;
21 int zbc_max; 20 int zbc_max;
@@ -23,9 +22,7 @@ struct nvkm_ltc {
23 u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; 22 u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT];
24}; 23};
25 24
26int nvkm_ltc_tags_alloc(struct nvkm_ltc *, u32 count, struct nvkm_mm_node **); 25void nvkm_ltc_tags_clear(struct nvkm_device *, u32 first, u32 count);
27void nvkm_ltc_tags_free(struct nvkm_ltc *, struct nvkm_mm_node **);
28void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count);
29 26
30int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); 27int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]);
31int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); 28int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
index dcd3deff27a4..975c42f620a0 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
@@ -1,68 +1,130 @@
1#ifndef __NVKM_MMU_H__ 1#ifndef __NVKM_MMU_H__
2#define __NVKM_MMU_H__ 2#define __NVKM_MMU_H__
3#include <core/subdev.h> 3#include <core/subdev.h>
4#include <core/mm.h>
5struct nvkm_device;
6struct nvkm_mem;
7
8struct nvkm_vm_pgt {
9 struct nvkm_memory *mem[2];
10 u32 refcount[2];
11};
12
13struct nvkm_vm_pgd {
14 struct list_head head;
15 struct nvkm_gpuobj *obj;
16};
17 4
18struct nvkm_vma { 5struct nvkm_vma {
19 struct list_head head; 6 struct list_head head;
20 int refcount; 7 struct rb_node tree;
21 struct nvkm_vm *vm; 8 u64 addr;
22 struct nvkm_mm_node *node; 9 u64 size:50;
23 u64 offset; 10 bool mapref:1; /* PTs (de)referenced on (un)map (vs pre-allocated). */
24 u32 access; 11 bool sparse:1; /* Unmapped PDEs/PTEs will not trigger MMU faults. */
12#define NVKM_VMA_PAGE_NONE 7
13 u8 page:3; /* Requested page type (index, or NONE for automatic). */
14 u8 refd:3; /* Current page type (index, or NONE for unreferenced). */
15 bool used:1; /* Region allocated. */
16 bool part:1; /* Region was split from an allocated region by map(). */
17 bool user:1; /* Region user-allocated. */
18 bool busy:1; /* Region busy (for temporarily preventing user access). */
19 struct nvkm_memory *memory; /* Memory currently mapped into VMA. */
20 struct nvkm_tags *tags; /* Compression tag reference. */
25}; 21};
26 22
27struct nvkm_vm { 23struct nvkm_vmm {
24 const struct nvkm_vmm_func *func;
28 struct nvkm_mmu *mmu; 25 struct nvkm_mmu *mmu;
29 26 const char *name;
27 u32 debug;
28 struct kref kref;
30 struct mutex mutex; 29 struct mutex mutex;
31 struct nvkm_mm mm;
32 struct kref refcount;
33 30
34 struct list_head pgd_list; 31 u64 start;
32 u64 limit;
33
34 struct nvkm_vmm_pt *pd;
35 struct list_head join;
36
37 struct list_head list;
38 struct rb_root free;
39 struct rb_root root;
40
41 bool bootstrapped;
35 atomic_t engref[NVKM_SUBDEV_NR]; 42 atomic_t engref[NVKM_SUBDEV_NR];
36 43
37 struct nvkm_vm_pgt *pgt; 44 dma_addr_t null;
38 u32 fpde; 45 void *nullp;
39 u32 lpde;
40}; 46};
41 47
42int nvkm_vm_new(struct nvkm_device *, u64 offset, u64 length, u64 mm_offset, 48int nvkm_vmm_new(struct nvkm_device *, u64 addr, u64 size, void *argv, u32 argc,
43 struct lock_class_key *, struct nvkm_vm **); 49 struct lock_class_key *, const char *name, struct nvkm_vmm **);
44int nvkm_vm_ref(struct nvkm_vm *, struct nvkm_vm **, struct nvkm_gpuobj *pgd); 50struct nvkm_vmm *nvkm_vmm_ref(struct nvkm_vmm *);
45int nvkm_vm_boot(struct nvkm_vm *, u64 size); 51void nvkm_vmm_unref(struct nvkm_vmm **);
46int nvkm_vm_get(struct nvkm_vm *, u64 size, u32 page_shift, u32 access, 52int nvkm_vmm_boot(struct nvkm_vmm *);
47 struct nvkm_vma *); 53int nvkm_vmm_join(struct nvkm_vmm *, struct nvkm_memory *inst);
48void nvkm_vm_put(struct nvkm_vma *); 54void nvkm_vmm_part(struct nvkm_vmm *, struct nvkm_memory *inst);
49void nvkm_vm_map(struct nvkm_vma *, struct nvkm_mem *); 55int nvkm_vmm_get(struct nvkm_vmm *, u8 page, u64 size, struct nvkm_vma **);
50void nvkm_vm_map_at(struct nvkm_vma *, u64 offset, struct nvkm_mem *); 56void nvkm_vmm_put(struct nvkm_vmm *, struct nvkm_vma **);
51void nvkm_vm_unmap(struct nvkm_vma *); 57
52void nvkm_vm_unmap_at(struct nvkm_vma *, u64 offset, u64 length); 58struct nvkm_vmm_map {
59 struct nvkm_memory *memory;
60 u64 offset;
61
62 struct nvkm_mm_node *mem;
63 struct scatterlist *sgl;
64 dma_addr_t *dma;
65 u64 off;
66
67 const struct nvkm_vmm_page *page;
68
69 struct nvkm_tags *tags;
70 u64 next;
71 u64 type;
72 u64 ctag;
73};
74
75int nvkm_vmm_map(struct nvkm_vmm *, struct nvkm_vma *, void *argv, u32 argc,
76 struct nvkm_vmm_map *);
77void nvkm_vmm_unmap(struct nvkm_vmm *, struct nvkm_vma *);
78
79struct nvkm_memory *nvkm_umem_search(struct nvkm_client *, u64);
80struct nvkm_vmm *nvkm_uvmm_search(struct nvkm_client *, u64 handle);
53 81
54struct nvkm_mmu { 82struct nvkm_mmu {
55 const struct nvkm_mmu_func *func; 83 const struct nvkm_mmu_func *func;
56 struct nvkm_subdev subdev; 84 struct nvkm_subdev subdev;
57 85
58 u64 limit;
59 u8 dma_bits; 86 u8 dma_bits;
60 u8 lpg_shift; 87
88 int heap_nr;
89 struct {
90#define NVKM_MEM_VRAM 0x01
91#define NVKM_MEM_HOST 0x02
92#define NVKM_MEM_COMP 0x04
93#define NVKM_MEM_DISP 0x08
94 u8 type;
95 u64 size;
96 } heap[4];
97
98 int type_nr;
99 struct {
100#define NVKM_MEM_KIND 0x10
101#define NVKM_MEM_MAPPABLE 0x20
102#define NVKM_MEM_COHERENT 0x40
103#define NVKM_MEM_UNCACHED 0x80
104 u8 type;
105 u8 heap;
106 } type[16];
107
108 struct nvkm_vmm *vmm;
109
110 struct {
111 struct mutex mutex;
112 struct list_head list;
113 } ptc, ptp;
114
115 struct nvkm_device_oclass user;
61}; 116};
62 117
63int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 118int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
64int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 119int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
65int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 120int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
66int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 121int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
122int g84_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
67int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); 123int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
124int gk104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
125int gk20a_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
126int gm200_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
127int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
128int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
129int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
68#endif 130#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
index 1bfd93b85575..9841f076da2e 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h
@@ -97,4 +97,5 @@ int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
97int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); 97int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
98int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); 98int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
99int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **); 99int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
100int gp100_therm_new(struct nvkm_device *, int, struct nvkm_therm **);
100#endif 101#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index f98f800cc011..ece650a0c5f9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -34,6 +34,7 @@
34#include "nouveau_gem.h" 34#include "nouveau_gem.h"
35#include "nouveau_chan.h" 35#include "nouveau_chan.h"
36#include "nouveau_abi16.h" 36#include "nouveau_abi16.h"
37#include "nouveau_vmm.h"
37 38
38static struct nouveau_abi16 * 39static struct nouveau_abi16 *
39nouveau_abi16(struct drm_file *file_priv) 40nouveau_abi16(struct drm_file *file_priv)
@@ -134,7 +135,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
134 } 135 }
135 136
136 if (chan->ntfy) { 137 if (chan->ntfy) {
137 nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma); 138 nouveau_vma_del(&chan->ntfy_vma);
138 nouveau_bo_unpin(chan->ntfy); 139 nouveau_bo_unpin(chan->ntfy);
139 drm_gem_object_unreference_unlocked(&chan->ntfy->gem); 140 drm_gem_object_unreference_unlocked(&chan->ntfy->gem);
140 } 141 }
@@ -184,29 +185,33 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
184 getparam->value = device->info.chipset; 185 getparam->value = device->info.chipset;
185 break; 186 break;
186 case NOUVEAU_GETPARAM_PCI_VENDOR: 187 case NOUVEAU_GETPARAM_PCI_VENDOR:
187 if (nvxx_device(device)->func->pci) 188 if (device->info.platform != NV_DEVICE_INFO_V0_SOC)
188 getparam->value = dev->pdev->vendor; 189 getparam->value = dev->pdev->vendor;
189 else 190 else
190 getparam->value = 0; 191 getparam->value = 0;
191 break; 192 break;
192 case NOUVEAU_GETPARAM_PCI_DEVICE: 193 case NOUVEAU_GETPARAM_PCI_DEVICE:
193 if (nvxx_device(device)->func->pci) 194 if (device->info.platform != NV_DEVICE_INFO_V0_SOC)
194 getparam->value = dev->pdev->device; 195 getparam->value = dev->pdev->device;
195 else 196 else
196 getparam->value = 0; 197 getparam->value = 0;
197 break; 198 break;
198 case NOUVEAU_GETPARAM_BUS_TYPE: 199 case NOUVEAU_GETPARAM_BUS_TYPE:
199 if (!nvxx_device(device)->func->pci) 200 switch (device->info.platform) {
200 getparam->value = 3; 201 case NV_DEVICE_INFO_V0_AGP : getparam->value = 0; break;
201 else 202 case NV_DEVICE_INFO_V0_PCI : getparam->value = 1; break;
202 if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP)) 203 case NV_DEVICE_INFO_V0_PCIE: getparam->value = 2; break;
203 getparam->value = 0; 204 case NV_DEVICE_INFO_V0_SOC : getparam->value = 3; break;
204 else 205 case NV_DEVICE_INFO_V0_IGP :
205 if (!pci_is_pcie(dev->pdev)) 206 if (!pci_is_pcie(dev->pdev))
206 getparam->value = 1; 207 getparam->value = 1;
207 else 208 else
208 getparam->value = 2; 209 getparam->value = 2;
209 break; 210 break;
211 default:
212 WARN_ON(1);
213 break;
214 }
210 case NOUVEAU_GETPARAM_FB_SIZE: 215 case NOUVEAU_GETPARAM_FB_SIZE:
211 getparam->value = drm->gem.vram_available; 216 getparam->value = drm->gem.vram_available;
212 break; 217 break;
@@ -329,8 +334,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
329 goto done; 334 goto done;
330 335
331 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 336 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
332 ret = nouveau_bo_vma_add(chan->ntfy, cli->vm, 337 ret = nouveau_vma_new(chan->ntfy, &cli->vmm, &chan->ntfy_vma);
333 &chan->ntfy_vma);
334 if (ret) 338 if (ret)
335 goto done; 339 goto done;
336 } 340 }
@@ -340,7 +344,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
340 if (ret) 344 if (ret)
341 goto done; 345 goto done;
342 346
343 ret = nvkm_mm_init(&chan->heap, 0, PAGE_SIZE, 1); 347 ret = nvkm_mm_init(&chan->heap, 0, 0, PAGE_SIZE, 1);
344done: 348done:
345 if (ret) 349 if (ret)
346 nouveau_abi16_chan_fini(abi16, chan); 350 nouveau_abi16_chan_fini(abi16, chan);
@@ -548,8 +552,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
548 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 552 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
549 args.target = NV_DMA_V0_TARGET_VM; 553 args.target = NV_DMA_V0_TARGET_VM;
550 args.access = NV_DMA_V0_ACCESS_VM; 554 args.access = NV_DMA_V0_ACCESS_VM;
551 args.start += chan->ntfy_vma.offset; 555 args.start += chan->ntfy_vma->addr;
552 args.limit += chan->ntfy_vma.offset; 556 args.limit += chan->ntfy_vma->addr;
553 } else 557 } else
554 if (drm->agp.bridge) { 558 if (drm->agp.bridge) {
555 args.target = NV_DMA_V0_TARGET_AGP; 559 args.target = NV_DMA_V0_TARGET_AGP;
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h
index 841cc556fad8..327747680324 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.h
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h
@@ -23,7 +23,7 @@ struct nouveau_abi16_chan {
23 struct nouveau_channel *chan; 23 struct nouveau_channel *chan;
24 struct list_head notifiers; 24 struct list_head notifiers;
25 struct nouveau_bo *ntfy; 25 struct nouveau_bo *ntfy;
26 struct nvkm_vma ntfy_vma; 26 struct nouveau_vma *ntfy_vma;
27 struct nvkm_mm heap; 27 struct nvkm_mm heap;
28}; 28};
29 29
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index dd6fba55ad5d..c4ef3a0a737e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -1478,9 +1478,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1478 case 1: 1478 case 1:
1479 entry->dpconf.link_bw = 270000; 1479 entry->dpconf.link_bw = 270000;
1480 break; 1480 break;
1481 default: 1481 case 2:
1482 entry->dpconf.link_bw = 540000; 1482 entry->dpconf.link_bw = 540000;
1483 break; 1483 break;
1484 case 3:
1485 default:
1486 entry->dpconf.link_bw = 810000;
1487 break;
1484 } 1488 }
1485 switch ((conf & 0x0f000000) >> 24) { 1489 switch ((conf & 0x0f000000) >> 24) {
1486 case 0xf: 1490 case 0xf:
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e427f80344c4..2615912430cc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -37,6 +37,12 @@
37#include "nouveau_bo.h" 37#include "nouveau_bo.h"
38#include "nouveau_ttm.h" 38#include "nouveau_ttm.h"
39#include "nouveau_gem.h" 39#include "nouveau_gem.h"
40#include "nouveau_mem.h"
41#include "nouveau_vmm.h"
42
43#include <nvif/class.h>
44#include <nvif/if500b.h>
45#include <nvif/if900b.h>
40 46
41/* 47/*
42 * NV10-NV40 tiling helpers 48 * NV10-NV40 tiling helpers
@@ -48,8 +54,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
48{ 54{
49 struct nouveau_drm *drm = nouveau_drm(dev); 55 struct nouveau_drm *drm = nouveau_drm(dev);
50 int i = reg - drm->tile.reg; 56 int i = reg - drm->tile.reg;
51 struct nvkm_device *device = nvxx_device(&drm->client.device); 57 struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
52 struct nvkm_fb *fb = device->fb;
53 struct nvkm_fb_tile *tile = &fb->tile.region[i]; 58 struct nvkm_fb_tile *tile = &fb->tile.region[i];
54 59
55 nouveau_fence_unref(&reg->fence); 60 nouveau_fence_unref(&reg->fence);
@@ -97,7 +102,7 @@ nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
97 102
98static struct nouveau_drm_tile * 103static struct nouveau_drm_tile *
99nv10_bo_set_tiling(struct drm_device *dev, u32 addr, 104nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
100 u32 size, u32 pitch, u32 flags) 105 u32 size, u32 pitch, u32 zeta)
101{ 106{
102 struct nouveau_drm *drm = nouveau_drm(dev); 107 struct nouveau_drm *drm = nouveau_drm(dev);
103 struct nvkm_fb *fb = nvxx_fb(&drm->client.device); 108 struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
@@ -120,8 +125,7 @@ nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
120 } 125 }
121 126
122 if (found) 127 if (found)
123 nv10_bo_update_tile_region(dev, found, addr, size, 128 nv10_bo_update_tile_region(dev, found, addr, size, pitch, zeta);
124 pitch, flags);
125 return found; 129 return found;
126} 130}
127 131
@@ -155,27 +159,27 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
155 struct nvif_device *device = &drm->client.device; 159 struct nvif_device *device = &drm->client.device;
156 160
157 if (device->info.family < NV_DEVICE_INFO_V0_TESLA) { 161 if (device->info.family < NV_DEVICE_INFO_V0_TESLA) {
158 if (nvbo->tile_mode) { 162 if (nvbo->mode) {
159 if (device->info.chipset >= 0x40) { 163 if (device->info.chipset >= 0x40) {
160 *align = 65536; 164 *align = 65536;
161 *size = roundup_64(*size, 64 * nvbo->tile_mode); 165 *size = roundup_64(*size, 64 * nvbo->mode);
162 166
163 } else if (device->info.chipset >= 0x30) { 167 } else if (device->info.chipset >= 0x30) {
164 *align = 32768; 168 *align = 32768;
165 *size = roundup_64(*size, 64 * nvbo->tile_mode); 169 *size = roundup_64(*size, 64 * nvbo->mode);
166 170
167 } else if (device->info.chipset >= 0x20) { 171 } else if (device->info.chipset >= 0x20) {
168 *align = 16384; 172 *align = 16384;
169 *size = roundup_64(*size, 64 * nvbo->tile_mode); 173 *size = roundup_64(*size, 64 * nvbo->mode);
170 174
171 } else if (device->info.chipset >= 0x10) { 175 } else if (device->info.chipset >= 0x10) {
172 *align = 16384; 176 *align = 16384;
173 *size = roundup_64(*size, 32 * nvbo->tile_mode); 177 *size = roundup_64(*size, 32 * nvbo->mode);
174 } 178 }
175 } 179 }
176 } else { 180 } else {
177 *size = roundup_64(*size, (1 << nvbo->page_shift)); 181 *size = roundup_64(*size, (1 << nvbo->page));
178 *align = max((1 << nvbo->page_shift), *align); 182 *align = max((1 << nvbo->page), *align);
179 } 183 }
180 184
181 *size = roundup_64(*size, PAGE_SIZE); 185 *size = roundup_64(*size, PAGE_SIZE);
@@ -187,11 +191,13 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
187 struct sg_table *sg, struct reservation_object *robj, 191 struct sg_table *sg, struct reservation_object *robj,
188 struct nouveau_bo **pnvbo) 192 struct nouveau_bo **pnvbo)
189{ 193{
190 struct nouveau_drm *drm = nouveau_drm(cli->dev); 194 struct nouveau_drm *drm = cli->drm;
191 struct nouveau_bo *nvbo; 195 struct nouveau_bo *nvbo;
196 struct nvif_mmu *mmu = &cli->mmu;
197 struct nvif_vmm *vmm = &cli->vmm.vmm;
192 size_t acc_size; 198 size_t acc_size;
193 int ret;
194 int type = ttm_bo_type_device; 199 int type = ttm_bo_type_device;
200 int ret, i, pi = -1;
195 201
196 if (!size) { 202 if (!size) {
197 NV_WARN(drm, "skipped size %016llx\n", size); 203 NV_WARN(drm, "skipped size %016llx\n", size);
@@ -207,19 +213,80 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
207 INIT_LIST_HEAD(&nvbo->head); 213 INIT_LIST_HEAD(&nvbo->head);
208 INIT_LIST_HEAD(&nvbo->entry); 214 INIT_LIST_HEAD(&nvbo->entry);
209 INIT_LIST_HEAD(&nvbo->vma_list); 215 INIT_LIST_HEAD(&nvbo->vma_list);
210 nvbo->tile_mode = tile_mode;
211 nvbo->tile_flags = tile_flags;
212 nvbo->bo.bdev = &drm->ttm.bdev; 216 nvbo->bo.bdev = &drm->ttm.bdev;
213 nvbo->cli = cli; 217 nvbo->cli = cli;
214 218
215 if (!nvxx_device(&drm->client.device)->func->cpu_coherent) 219 /* This is confusing, and doesn't actually mean we want an uncached
216 nvbo->force_coherent = flags & TTM_PL_FLAG_UNCACHED; 220 * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated
221 * into in nouveau_gem_new().
222 */
223 if (flags & TTM_PL_FLAG_UNCACHED) {
224 /* Determine if we can get a cache-coherent map, forcing
225 * uncached mapping if we can't.
226 */
227 if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED)
228 nvbo->force_coherent = true;
229 }
230
231 if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) {
232 nvbo->kind = (tile_flags & 0x0000ff00) >> 8;
233 if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
234 kfree(nvbo);
235 return -EINVAL;
236 }
237
238 nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind;
239 } else
240 if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
241 nvbo->kind = (tile_flags & 0x00007f00) >> 8;
242 nvbo->comp = (tile_flags & 0x00030000) >> 16;
243 if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
244 kfree(nvbo);
245 return -EINVAL;
246 }
247 } else {
248 nvbo->zeta = (tile_flags & 0x00000007);
249 }
250 nvbo->mode = tile_mode;
251 nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG);
252
253 /* Determine the desirable target GPU page size for the buffer. */
254 for (i = 0; i < vmm->page_nr; i++) {
255 /* Because we cannot currently allow VMM maps to fail
256 * during buffer migration, we need to determine page
257 * size for the buffer up-front, and pre-allocate its
258 * page tables.
259 *
260 * Skip page sizes that can't support needed domains.
261 */
262 if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE &&
263 (flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram)
264 continue;
265 if ((flags & TTM_PL_FLAG_TT ) && !vmm->page[i].host)
266 continue;
267
268 /* Select this page size if it's the first that supports
269 * the potential memory domains, or when it's compatible
270 * with the requested compression settings.
271 */
272 if (pi < 0 || !nvbo->comp || vmm->page[i].comp)
273 pi = i;
274
275 /* Stop once the buffer is larger than the current page size. */
276 if (size >= 1ULL << vmm->page[i].shift)
277 break;
278 }
279
280 if (WARN_ON(pi < 0))
281 return -EINVAL;
217 282
218 nvbo->page_shift = 12; 283 /* Disable compression if suitable settings couldn't be found. */
219 if (drm->client.vm) { 284 if (nvbo->comp && !vmm->page[pi].comp) {
220 if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) 285 if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100)
221 nvbo->page_shift = drm->client.vm->mmu->lpg_shift; 286 nvbo->kind = mmu->kind[nvbo->kind];
287 nvbo->comp = 0;
222 } 288 }
289 nvbo->page = vmm->page[pi].shift;
223 290
224 nouveau_bo_fixup_align(nvbo, flags, &align, &size); 291 nouveau_bo_fixup_align(nvbo, flags, &align, &size);
225 nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; 292 nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
@@ -262,7 +329,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
262 unsigned i, fpfn, lpfn; 329 unsigned i, fpfn, lpfn;
263 330
264 if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS && 331 if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
265 nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && 332 nvbo->mode && (type & TTM_PL_FLAG_VRAM) &&
266 nvbo->bo.mem.num_pages < vram_pages / 4) { 333 nvbo->bo.mem.num_pages < vram_pages / 4) {
267 /* 334 /*
268 * Make sure that the color and depth buffers are handled 335 * Make sure that the color and depth buffers are handled
@@ -270,7 +337,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
270 * speed up when alpha-blending and depth-test are enabled 337 * speed up when alpha-blending and depth-test are enabled
271 * at the same time. 338 * at the same time.
272 */ 339 */
273 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { 340 if (nvbo->zeta) {
274 fpfn = vram_pages / 2; 341 fpfn = vram_pages / 2;
275 lpfn = ~0; 342 lpfn = ~0;
276 } else { 343 } else {
@@ -321,14 +388,10 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig)
321 388
322 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA && 389 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
323 memtype == TTM_PL_FLAG_VRAM && contig) { 390 memtype == TTM_PL_FLAG_VRAM && contig) {
324 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) { 391 if (!nvbo->contig) {
325 if (bo->mem.mem_type == TTM_PL_VRAM) { 392 nvbo->contig = true;
326 struct nvkm_mem *mem = bo->mem.mm_node;
327 if (!nvkm_mm_contiguous(mem->mem))
328 evict = true;
329 }
330 nvbo->tile_flags &= ~NOUVEAU_GEM_TILE_NONCONTIG;
331 force = true; 393 force = true;
394 evict = true;
332 } 395 }
333 } 396 }
334 397
@@ -376,7 +439,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig)
376 439
377out: 440out:
378 if (force && ret) 441 if (force && ret)
379 nvbo->tile_flags |= NOUVEAU_GEM_TILE_NONCONTIG; 442 nvbo->contig = false;
380 ttm_bo_unreserve(bo); 443 ttm_bo_unreserve(bo);
381 return ret; 444 return ret;
382} 445}
@@ -446,7 +509,6 @@ void
446nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) 509nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)
447{ 510{
448 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 511 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
449 struct nvkm_device *device = nvxx_device(&drm->client.device);
450 struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; 512 struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
451 int i; 513 int i;
452 514
@@ -458,7 +520,8 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)
458 return; 520 return;
459 521
460 for (i = 0; i < ttm_dma->ttm.num_pages; i++) 522 for (i = 0; i < ttm_dma->ttm.num_pages; i++)
461 dma_sync_single_for_device(device->dev, ttm_dma->dma_address[i], 523 dma_sync_single_for_device(drm->dev->dev,
524 ttm_dma->dma_address[i],
462 PAGE_SIZE, DMA_TO_DEVICE); 525 PAGE_SIZE, DMA_TO_DEVICE);
463} 526}
464 527
@@ -466,7 +529,6 @@ void
466nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) 529nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
467{ 530{
468 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 531 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
469 struct nvkm_device *device = nvxx_device(&drm->client.device);
470 struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; 532 struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
471 int i; 533 int i;
472 534
@@ -478,7 +540,7 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
478 return; 540 return;
479 541
480 for (i = 0; i < ttm_dma->ttm.num_pages; i++) 542 for (i = 0; i < ttm_dma->ttm.num_pages; i++)
481 dma_sync_single_for_cpu(device->dev, ttm_dma->dma_address[i], 543 dma_sync_single_for_cpu(drm->dev->dev, ttm_dma->dma_address[i],
482 PAGE_SIZE, DMA_FROM_DEVICE); 544 PAGE_SIZE, DMA_FROM_DEVICE);
483} 545}
484 546
@@ -568,6 +630,7 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
568 struct ttm_mem_type_manager *man) 630 struct ttm_mem_type_manager *man)
569{ 631{
570 struct nouveau_drm *drm = nouveau_bdev(bdev); 632 struct nouveau_drm *drm = nouveau_bdev(bdev);
633 struct nvif_mmu *mmu = &drm->client.mmu;
571 634
572 switch (type) { 635 switch (type) {
573 case TTM_PL_SYSTEM: 636 case TTM_PL_SYSTEM:
@@ -584,7 +647,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
584 647
585 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { 648 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
586 /* Some BARs do not support being ioremapped WC */ 649 /* Some BARs do not support being ioremapped WC */
587 if (nvxx_bar(&drm->client.device)->iomap_uncached) { 650 const u8 type = mmu->type[drm->ttm.type_vram].type;
651 if (type & NVIF_MEM_UNCACHED) {
588 man->available_caching = TTM_PL_FLAG_UNCACHED; 652 man->available_caching = TTM_PL_FLAG_UNCACHED;
589 man->default_caching = TTM_PL_FLAG_UNCACHED; 653 man->default_caching = TTM_PL_FLAG_UNCACHED;
590 } 654 }
@@ -659,14 +723,14 @@ static int
659nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 723nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
660 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 724 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
661{ 725{
662 struct nvkm_mem *mem = old_reg->mm_node; 726 struct nouveau_mem *mem = nouveau_mem(old_reg);
663 int ret = RING_SPACE(chan, 10); 727 int ret = RING_SPACE(chan, 10);
664 if (ret == 0) { 728 if (ret == 0) {
665 BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8); 729 BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8);
666 OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); 730 OUT_RING (chan, upper_32_bits(mem->vma[0].addr));
667 OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); 731 OUT_RING (chan, lower_32_bits(mem->vma[0].addr));
668 OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); 732 OUT_RING (chan, upper_32_bits(mem->vma[1].addr));
669 OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); 733 OUT_RING (chan, lower_32_bits(mem->vma[1].addr));
670 OUT_RING (chan, PAGE_SIZE); 734 OUT_RING (chan, PAGE_SIZE);
671 OUT_RING (chan, PAGE_SIZE); 735 OUT_RING (chan, PAGE_SIZE);
672 OUT_RING (chan, PAGE_SIZE); 736 OUT_RING (chan, PAGE_SIZE);
@@ -691,9 +755,9 @@ static int
691nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 755nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
692 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 756 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
693{ 757{
694 struct nvkm_mem *mem = old_reg->mm_node; 758 struct nouveau_mem *mem = nouveau_mem(old_reg);
695 u64 src_offset = mem->vma[0].offset; 759 u64 src_offset = mem->vma[0].addr;
696 u64 dst_offset = mem->vma[1].offset; 760 u64 dst_offset = mem->vma[1].addr;
697 u32 page_count = new_reg->num_pages; 761 u32 page_count = new_reg->num_pages;
698 int ret; 762 int ret;
699 763
@@ -729,9 +793,9 @@ static int
729nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 793nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
730 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 794 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
731{ 795{
732 struct nvkm_mem *mem = old_reg->mm_node; 796 struct nouveau_mem *mem = nouveau_mem(old_reg);
733 u64 src_offset = mem->vma[0].offset; 797 u64 src_offset = mem->vma[0].addr;
734 u64 dst_offset = mem->vma[1].offset; 798 u64 dst_offset = mem->vma[1].addr;
735 u32 page_count = new_reg->num_pages; 799 u32 page_count = new_reg->num_pages;
736 int ret; 800 int ret;
737 801
@@ -768,9 +832,9 @@ static int
768nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 832nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
769 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 833 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
770{ 834{
771 struct nvkm_mem *mem = old_reg->mm_node; 835 struct nouveau_mem *mem = nouveau_mem(old_reg);
772 u64 src_offset = mem->vma[0].offset; 836 u64 src_offset = mem->vma[0].addr;
773 u64 dst_offset = mem->vma[1].offset; 837 u64 dst_offset = mem->vma[1].addr;
774 u32 page_count = new_reg->num_pages; 838 u32 page_count = new_reg->num_pages;
775 int ret; 839 int ret;
776 840
@@ -806,14 +870,14 @@ static int
806nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 870nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
807 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 871 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
808{ 872{
809 struct nvkm_mem *mem = old_reg->mm_node; 873 struct nouveau_mem *mem = nouveau_mem(old_reg);
810 int ret = RING_SPACE(chan, 7); 874 int ret = RING_SPACE(chan, 7);
811 if (ret == 0) { 875 if (ret == 0) {
812 BEGIN_NV04(chan, NvSubCopy, 0x0320, 6); 876 BEGIN_NV04(chan, NvSubCopy, 0x0320, 6);
813 OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); 877 OUT_RING (chan, upper_32_bits(mem->vma[0].addr));
814 OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); 878 OUT_RING (chan, lower_32_bits(mem->vma[0].addr));
815 OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); 879 OUT_RING (chan, upper_32_bits(mem->vma[1].addr));
816 OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); 880 OUT_RING (chan, lower_32_bits(mem->vma[1].addr));
817 OUT_RING (chan, 0x00000000 /* COPY */); 881 OUT_RING (chan, 0x00000000 /* COPY */);
818 OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT); 882 OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT);
819 } 883 }
@@ -824,15 +888,15 @@ static int
824nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 888nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
825 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 889 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
826{ 890{
827 struct nvkm_mem *mem = old_reg->mm_node; 891 struct nouveau_mem *mem = nouveau_mem(old_reg);
828 int ret = RING_SPACE(chan, 7); 892 int ret = RING_SPACE(chan, 7);
829 if (ret == 0) { 893 if (ret == 0) {
830 BEGIN_NV04(chan, NvSubCopy, 0x0304, 6); 894 BEGIN_NV04(chan, NvSubCopy, 0x0304, 6);
831 OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT); 895 OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT);
832 OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); 896 OUT_RING (chan, upper_32_bits(mem->vma[0].addr));
833 OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); 897 OUT_RING (chan, lower_32_bits(mem->vma[0].addr));
834 OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); 898 OUT_RING (chan, upper_32_bits(mem->vma[1].addr));
835 OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); 899 OUT_RING (chan, lower_32_bits(mem->vma[1].addr));
836 OUT_RING (chan, 0x00000000 /* MODE_COPY, QUERY_NONE */); 900 OUT_RING (chan, 0x00000000 /* MODE_COPY, QUERY_NONE */);
837 } 901 }
838 return ret; 902 return ret;
@@ -858,12 +922,12 @@ static int
858nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, 922nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
859 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) 923 struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
860{ 924{
861 struct nvkm_mem *mem = old_reg->mm_node; 925 struct nouveau_mem *mem = nouveau_mem(old_reg);
862 u64 length = (new_reg->num_pages << PAGE_SHIFT); 926 u64 length = (new_reg->num_pages << PAGE_SHIFT);
863 u64 src_offset = mem->vma[0].offset; 927 u64 src_offset = mem->vma[0].addr;
864 u64 dst_offset = mem->vma[1].offset; 928 u64 dst_offset = mem->vma[1].addr;
865 int src_tiled = !!mem->memtype; 929 int src_tiled = !!mem->kind;
866 int dst_tiled = !!((struct nvkm_mem *)new_reg->mm_node)->memtype; 930 int dst_tiled = !!nouveau_mem(new_reg)->kind;
867 int ret; 931 int ret;
868 932
869 while (length) { 933 while (length) {
@@ -1000,25 +1064,31 @@ static int
1000nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, 1064nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
1001 struct ttm_mem_reg *reg) 1065 struct ttm_mem_reg *reg)
1002{ 1066{
1003 struct nvkm_mem *old_mem = bo->mem.mm_node; 1067 struct nouveau_mem *old_mem = nouveau_mem(&bo->mem);
1004 struct nvkm_mem *new_mem = reg->mm_node; 1068 struct nouveau_mem *new_mem = nouveau_mem(reg);
1005 u64 size = (u64)reg->num_pages << PAGE_SHIFT; 1069 struct nvif_vmm *vmm = &drm->client.vmm.vmm;
1006 int ret; 1070 int ret;
1007 1071
1008 ret = nvkm_vm_get(drm->client.vm, size, old_mem->page_shift, 1072 ret = nvif_vmm_get(vmm, LAZY, false, old_mem->mem.page, 0,
1009 NV_MEM_ACCESS_RW, &old_mem->vma[0]); 1073 old_mem->mem.size, &old_mem->vma[0]);
1010 if (ret) 1074 if (ret)
1011 return ret; 1075 return ret;
1012 1076
1013 ret = nvkm_vm_get(drm->client.vm, size, new_mem->page_shift, 1077 ret = nvif_vmm_get(vmm, LAZY, false, new_mem->mem.page, 0,
1014 NV_MEM_ACCESS_RW, &old_mem->vma[1]); 1078 new_mem->mem.size, &old_mem->vma[1]);
1079 if (ret)
1080 goto done;
1081
1082 ret = nouveau_mem_map(old_mem, vmm, &old_mem->vma[0]);
1083 if (ret)
1084 goto done;
1085
1086 ret = nouveau_mem_map(new_mem, vmm, &old_mem->vma[1]);
1087done:
1015 if (ret) { 1088 if (ret) {
1016 nvkm_vm_put(&old_mem->vma[0]); 1089 nvif_vmm_put(vmm, &old_mem->vma[1]);
1017 return ret; 1090 nvif_vmm_put(vmm, &old_mem->vma[0]);
1018 } 1091 }
1019
1020 nvkm_vm_map(&old_mem->vma[0], old_mem);
1021 nvkm_vm_map(&old_mem->vma[1], new_mem);
1022 return 0; 1092 return 0;
1023} 1093}
1024 1094
@@ -1200,21 +1270,23 @@ static void
1200nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, 1270nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
1201 struct ttm_mem_reg *new_reg) 1271 struct ttm_mem_reg *new_reg)
1202{ 1272{
1273 struct nouveau_mem *mem = new_reg ? nouveau_mem(new_reg) : NULL;
1203 struct nouveau_bo *nvbo = nouveau_bo(bo); 1274 struct nouveau_bo *nvbo = nouveau_bo(bo);
1204 struct nvkm_vma *vma; 1275 struct nouveau_vma *vma;
1205 1276
1206 /* ttm can now (stupidly) pass the driver bos it didn't create... */ 1277 /* ttm can now (stupidly) pass the driver bos it didn't create... */
1207 if (bo->destroy != nouveau_bo_del_ttm) 1278 if (bo->destroy != nouveau_bo_del_ttm)
1208 return; 1279 return;
1209 1280
1210 list_for_each_entry(vma, &nvbo->vma_list, head) { 1281 if (mem && new_reg->mem_type != TTM_PL_SYSTEM &&
1211 if (new_reg && new_reg->mem_type != TTM_PL_SYSTEM && 1282 mem->mem.page == nvbo->page) {
1212 (new_reg->mem_type == TTM_PL_VRAM || 1283 list_for_each_entry(vma, &nvbo->vma_list, head) {
1213 nvbo->page_shift != vma->vm->mmu->lpg_shift)) { 1284 nouveau_vma_map(vma, mem);
1214 nvkm_vm_map(vma, new_reg->mm_node); 1285 }
1215 } else { 1286 } else {
1287 list_for_each_entry(vma, &nvbo->vma_list, head) {
1216 WARN_ON(ttm_bo_wait(bo, false, false)); 1288 WARN_ON(ttm_bo_wait(bo, false, false));
1217 nvkm_vm_unmap(vma); 1289 nouveau_vma_unmap(vma);
1218 } 1290 }
1219 } 1291 }
1220} 1292}
@@ -1234,8 +1306,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_reg,
1234 1306
1235 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) { 1307 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
1236 *new_tile = nv10_bo_set_tiling(dev, offset, new_reg->size, 1308 *new_tile = nv10_bo_set_tiling(dev, offset, new_reg->size,
1237 nvbo->tile_mode, 1309 nvbo->mode, nvbo->zeta);
1238 nvbo->tile_flags);
1239 } 1310 }
1240 1311
1241 return 0; 1312 return 0;
@@ -1331,8 +1402,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1331 struct ttm_mem_type_manager *man = &bdev->man[reg->mem_type]; 1402 struct ttm_mem_type_manager *man = &bdev->man[reg->mem_type];
1332 struct nouveau_drm *drm = nouveau_bdev(bdev); 1403 struct nouveau_drm *drm = nouveau_bdev(bdev);
1333 struct nvkm_device *device = nvxx_device(&drm->client.device); 1404 struct nvkm_device *device = nvxx_device(&drm->client.device);
1334 struct nvkm_mem *mem = reg->mm_node; 1405 struct nouveau_mem *mem = nouveau_mem(reg);
1335 int ret;
1336 1406
1337 reg->bus.addr = NULL; 1407 reg->bus.addr = NULL;
1338 reg->bus.offset = 0; 1408 reg->bus.offset = 0;
@@ -1353,7 +1423,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1353 reg->bus.is_iomem = !drm->agp.cma; 1423 reg->bus.is_iomem = !drm->agp.cma;
1354 } 1424 }
1355#endif 1425#endif
1356 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA || !mem->memtype) 1426 if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || !mem->kind)
1357 /* untiled */ 1427 /* untiled */
1358 break; 1428 break;
1359 /* fallthrough, tiled memory */ 1429 /* fallthrough, tiled memory */
@@ -1361,19 +1431,40 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1361 reg->bus.offset = reg->start << PAGE_SHIFT; 1431 reg->bus.offset = reg->start << PAGE_SHIFT;
1362 reg->bus.base = device->func->resource_addr(device, 1); 1432 reg->bus.base = device->func->resource_addr(device, 1);
1363 reg->bus.is_iomem = true; 1433 reg->bus.is_iomem = true;
1364 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { 1434 if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
1365 struct nvkm_bar *bar = nvxx_bar(&drm->client.device); 1435 union {
1366 int page_shift = 12; 1436 struct nv50_mem_map_v0 nv50;
1367 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI) 1437 struct gf100_mem_map_v0 gf100;
1368 page_shift = mem->page_shift; 1438 } args;
1439 u64 handle, length;
1440 u32 argc = 0;
1441 int ret;
1442
1443 switch (mem->mem.object.oclass) {
1444 case NVIF_CLASS_MEM_NV50:
1445 args.nv50.version = 0;
1446 args.nv50.ro = 0;
1447 args.nv50.kind = mem->kind;
1448 args.nv50.comp = mem->comp;
1449 break;
1450 case NVIF_CLASS_MEM_GF100:
1451 args.gf100.version = 0;
1452 args.gf100.ro = 0;
1453 args.gf100.kind = mem->kind;
1454 break;
1455 default:
1456 WARN_ON(1);
1457 break;
1458 }
1369 1459
1370 ret = nvkm_bar_umap(bar, mem->size << 12, page_shift, 1460 ret = nvif_object_map_handle(&mem->mem.object,
1371 &mem->bar_vma); 1461 &argc, argc,
1372 if (ret) 1462 &handle, &length);
1373 return ret; 1463 if (ret != 1)
1464 return ret ? ret : -EINVAL;
1374 1465
1375 nvkm_vm_map(&mem->bar_vma, mem); 1466 reg->bus.base = 0;
1376 reg->bus.offset = mem->bar_vma.offset; 1467 reg->bus.offset = handle;
1377 } 1468 }
1378 break; 1469 break;
1379 default: 1470 default:
@@ -1385,13 +1476,22 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1385static void 1476static void
1386nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) 1477nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1387{ 1478{
1388 struct nvkm_mem *mem = reg->mm_node; 1479 struct nouveau_drm *drm = nouveau_bdev(bdev);
1389 1480 struct nouveau_mem *mem = nouveau_mem(reg);
1390 if (!mem->bar_vma.node)
1391 return;
1392 1481
1393 nvkm_vm_unmap(&mem->bar_vma); 1482 if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
1394 nvkm_vm_put(&mem->bar_vma); 1483 switch (reg->mem_type) {
1484 case TTM_PL_TT:
1485 if (mem->kind)
1486 nvif_object_unmap_handle(&mem->mem.object);
1487 break;
1488 case TTM_PL_VRAM:
1489 nvif_object_unmap_handle(&mem->mem.object);
1490 break;
1491 default:
1492 break;
1493 }
1494 }
1395} 1495}
1396 1496
1397static int 1497static int
@@ -1408,7 +1508,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
1408 */ 1508 */
1409 if (bo->mem.mem_type != TTM_PL_VRAM) { 1509 if (bo->mem.mem_type != TTM_PL_VRAM) {
1410 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA || 1510 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA ||
1411 !nouveau_bo_tile_layout(nvbo)) 1511 !nvbo->kind)
1412 return 0; 1512 return 0;
1413 1513
1414 if (bo->mem.mem_type == TTM_PL_SYSTEM) { 1514 if (bo->mem.mem_type == TTM_PL_SYSTEM) {
@@ -1445,9 +1545,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1445{ 1545{
1446 struct ttm_dma_tt *ttm_dma = (void *)ttm; 1546 struct ttm_dma_tt *ttm_dma = (void *)ttm;
1447 struct nouveau_drm *drm; 1547 struct nouveau_drm *drm;
1448 struct nvkm_device *device; 1548 struct device *dev;
1449 struct drm_device *dev;
1450 struct device *pdev;
1451 unsigned i; 1549 unsigned i;
1452 int r; 1550 int r;
1453 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); 1551 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
@@ -1464,9 +1562,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1464 } 1562 }
1465 1563
1466 drm = nouveau_bdev(ttm->bdev); 1564 drm = nouveau_bdev(ttm->bdev);
1467 device = nvxx_device(&drm->client.device); 1565 dev = drm->dev->dev;
1468 dev = drm->dev;
1469 pdev = device->dev;
1470 1566
1471#if IS_ENABLED(CONFIG_AGP) 1567#if IS_ENABLED(CONFIG_AGP)
1472 if (drm->agp.bridge) { 1568 if (drm->agp.bridge) {
@@ -1476,7 +1572,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1476 1572
1477#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86) 1573#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
1478 if (swiotlb_nr_tbl()) { 1574 if (swiotlb_nr_tbl()) {
1479 return ttm_dma_populate((void *)ttm, dev->dev); 1575 return ttm_dma_populate((void *)ttm, dev);
1480 } 1576 }
1481#endif 1577#endif
1482 1578
@@ -1488,12 +1584,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1488 for (i = 0; i < ttm->num_pages; i++) { 1584 for (i = 0; i < ttm->num_pages; i++) {
1489 dma_addr_t addr; 1585 dma_addr_t addr;
1490 1586
1491 addr = dma_map_page(pdev, ttm->pages[i], 0, PAGE_SIZE, 1587 addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE,
1492 DMA_BIDIRECTIONAL); 1588 DMA_BIDIRECTIONAL);
1493 1589
1494 if (dma_mapping_error(pdev, addr)) { 1590 if (dma_mapping_error(dev, addr)) {
1495 while (i--) { 1591 while (i--) {
1496 dma_unmap_page(pdev, ttm_dma->dma_address[i], 1592 dma_unmap_page(dev, ttm_dma->dma_address[i],
1497 PAGE_SIZE, DMA_BIDIRECTIONAL); 1593 PAGE_SIZE, DMA_BIDIRECTIONAL);
1498 ttm_dma->dma_address[i] = 0; 1594 ttm_dma->dma_address[i] = 0;
1499 } 1595 }
@@ -1511,9 +1607,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1511{ 1607{
1512 struct ttm_dma_tt *ttm_dma = (void *)ttm; 1608 struct ttm_dma_tt *ttm_dma = (void *)ttm;
1513 struct nouveau_drm *drm; 1609 struct nouveau_drm *drm;
1514 struct nvkm_device *device; 1610 struct device *dev;
1515 struct drm_device *dev;
1516 struct device *pdev;
1517 unsigned i; 1611 unsigned i;
1518 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); 1612 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
1519 1613
@@ -1521,9 +1615,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1521 return; 1615 return;
1522 1616
1523 drm = nouveau_bdev(ttm->bdev); 1617 drm = nouveau_bdev(ttm->bdev);
1524 device = nvxx_device(&drm->client.device); 1618 dev = drm->dev->dev;
1525 dev = drm->dev;
1526 pdev = device->dev;
1527 1619
1528#if IS_ENABLED(CONFIG_AGP) 1620#if IS_ENABLED(CONFIG_AGP)
1529 if (drm->agp.bridge) { 1621 if (drm->agp.bridge) {
@@ -1534,14 +1626,14 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1534 1626
1535#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86) 1627#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
1536 if (swiotlb_nr_tbl()) { 1628 if (swiotlb_nr_tbl()) {
1537 ttm_dma_unpopulate((void *)ttm, dev->dev); 1629 ttm_dma_unpopulate((void *)ttm, dev);
1538 return; 1630 return;
1539 } 1631 }
1540#endif 1632#endif
1541 1633
1542 for (i = 0; i < ttm->num_pages; i++) { 1634 for (i = 0; i < ttm->num_pages; i++) {
1543 if (ttm_dma->dma_address[i]) { 1635 if (ttm_dma->dma_address[i]) {
1544 dma_unmap_page(pdev, ttm_dma->dma_address[i], PAGE_SIZE, 1636 dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE,
1545 DMA_BIDIRECTIONAL); 1637 DMA_BIDIRECTIONAL);
1546 } 1638 }
1547 } 1639 }
@@ -1576,48 +1668,3 @@ struct ttm_bo_driver nouveau_bo_driver = {
1576 .io_mem_free = &nouveau_ttm_io_mem_free, 1668 .io_mem_free = &nouveau_ttm_io_mem_free,
1577 .io_mem_pfn = ttm_bo_default_io_mem_pfn, 1669 .io_mem_pfn = ttm_bo_default_io_mem_pfn,
1578}; 1670};
1579
1580struct nvkm_vma *
1581nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nvkm_vm *vm)
1582{
1583 struct nvkm_vma *vma;
1584 list_for_each_entry(vma, &nvbo->vma_list, head) {
1585 if (vma->vm == vm)
1586 return vma;
1587 }
1588
1589 return NULL;
1590}
1591
1592int
1593nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nvkm_vm *vm,
1594 struct nvkm_vma *vma)
1595{
1596 const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
1597 int ret;
1598
1599 ret = nvkm_vm_get(vm, size, nvbo->page_shift,
1600 NV_MEM_ACCESS_RW, vma);
1601 if (ret)
1602 return ret;
1603
1604 if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
1605 (nvbo->bo.mem.mem_type == TTM_PL_VRAM ||
1606 nvbo->page_shift != vma->vm->mmu->lpg_shift))
1607 nvkm_vm_map(vma, nvbo->bo.mem.mm_node);
1608
1609 list_add_tail(&vma->head, &nvbo->vma_list);
1610 vma->refcount = 1;
1611 return 0;
1612}
1613
1614void
1615nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nvkm_vma *vma)
1616{
1617 if (vma->node) {
1618 if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM)
1619 nvkm_vm_unmap(vma);
1620 nvkm_vm_put(vma);
1621 list_del(&vma->head);
1622 }
1623}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h
index b06a5385d6dd..23002bdd94a8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.h
@@ -24,12 +24,16 @@ struct nouveau_bo {
24 bool validate_mapped; 24 bool validate_mapped;
25 25
26 struct list_head vma_list; 26 struct list_head vma_list;
27 unsigned page_shift;
28 27
29 struct nouveau_cli *cli; 28 struct nouveau_cli *cli;
30 29
31 u32 tile_mode; 30 unsigned contig:1;
32 u32 tile_flags; 31 unsigned page:5;
32 unsigned kind:8;
33 unsigned comp:3;
34 unsigned zeta:3;
35 unsigned mode;
36
33 struct nouveau_drm_tile *tile; 37 struct nouveau_drm_tile *tile;
34 38
35 /* Only valid if allocated via nouveau_gem_new() and iff you hold a 39 /* Only valid if allocated via nouveau_gem_new() and iff you hold a
@@ -89,13 +93,6 @@ int nouveau_bo_validate(struct nouveau_bo *, bool interruptible,
89void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo); 93void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo);
90void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo); 94void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo);
91 95
92struct nvkm_vma *
93nouveau_bo_vma_find(struct nouveau_bo *, struct nvkm_vm *);
94
95int nouveau_bo_vma_add(struct nouveau_bo *, struct nvkm_vm *,
96 struct nvkm_vma *);
97void nouveau_bo_vma_del(struct nouveau_bo *, struct nvkm_vma *);
98
99/* TODO: submit equivalent to TTM generic API upstream? */ 96/* TODO: submit equivalent to TTM generic API upstream? */
100static inline void __iomem * 97static inline void __iomem *
101nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) 98nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index dbc41fa86ee8..af1116655910 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -40,6 +40,7 @@
40#include "nouveau_chan.h" 40#include "nouveau_chan.h"
41#include "nouveau_fence.h" 41#include "nouveau_fence.h"
42#include "nouveau_abi16.h" 42#include "nouveau_abi16.h"
43#include "nouveau_vmm.h"
43 44
44MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); 45MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM");
45int nouveau_vram_pushbuf; 46int nouveau_vram_pushbuf;
@@ -83,6 +84,14 @@ nouveau_channel_del(struct nouveau_channel **pchan)
83{ 84{
84 struct nouveau_channel *chan = *pchan; 85 struct nouveau_channel *chan = *pchan;
85 if (chan) { 86 if (chan) {
87 struct nouveau_cli *cli = (void *)chan->user.client;
88 bool super;
89
90 if (cli) {
91 super = cli->base.super;
92 cli->base.super = true;
93 }
94
86 if (chan->fence) 95 if (chan->fence)
87 nouveau_fence(chan->drm)->context_del(chan); 96 nouveau_fence(chan->drm)->context_del(chan);
88 nvif_object_fini(&chan->nvsw); 97 nvif_object_fini(&chan->nvsw);
@@ -91,12 +100,15 @@ nouveau_channel_del(struct nouveau_channel **pchan)
91 nvif_notify_fini(&chan->kill); 100 nvif_notify_fini(&chan->kill);
92 nvif_object_fini(&chan->user); 101 nvif_object_fini(&chan->user);
93 nvif_object_fini(&chan->push.ctxdma); 102 nvif_object_fini(&chan->push.ctxdma);
94 nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma); 103 nouveau_vma_del(&chan->push.vma);
95 nouveau_bo_unmap(chan->push.buffer); 104 nouveau_bo_unmap(chan->push.buffer);
96 if (chan->push.buffer && chan->push.buffer->pin_refcnt) 105 if (chan->push.buffer && chan->push.buffer->pin_refcnt)
97 nouveau_bo_unpin(chan->push.buffer); 106 nouveau_bo_unpin(chan->push.buffer);
98 nouveau_bo_ref(NULL, &chan->push.buffer); 107 nouveau_bo_ref(NULL, &chan->push.buffer);
99 kfree(chan); 108 kfree(chan);
109
110 if (cli)
111 cli->base.super = super;
100 } 112 }
101 *pchan = NULL; 113 *pchan = NULL;
102} 114}
@@ -106,7 +118,6 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
106 u32 size, struct nouveau_channel **pchan) 118 u32 size, struct nouveau_channel **pchan)
107{ 119{
108 struct nouveau_cli *cli = (void *)device->object.client; 120 struct nouveau_cli *cli = (void *)device->object.client;
109 struct nvkm_mmu *mmu = nvxx_mmu(device);
110 struct nv_dma_v0 args = {}; 121 struct nv_dma_v0 args = {};
111 struct nouveau_channel *chan; 122 struct nouveau_channel *chan;
112 u32 target; 123 u32 target;
@@ -142,11 +153,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
142 * pushbuf lives in, this is because the GEM code requires that 153 * pushbuf lives in, this is because the GEM code requires that
143 * we be able to call out to other (indirect) push buffers 154 * we be able to call out to other (indirect) push buffers
144 */ 155 */
145 chan->push.vma.offset = chan->push.buffer->bo.offset; 156 chan->push.addr = chan->push.buffer->bo.offset;
146 157
147 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 158 if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
148 ret = nouveau_bo_vma_add(chan->push.buffer, cli->vm, 159 ret = nouveau_vma_new(chan->push.buffer, &cli->vmm,
149 &chan->push.vma); 160 &chan->push.vma);
150 if (ret) { 161 if (ret) {
151 nouveau_channel_del(pchan); 162 nouveau_channel_del(pchan);
152 return ret; 163 return ret;
@@ -155,7 +166,9 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
155 args.target = NV_DMA_V0_TARGET_VM; 166 args.target = NV_DMA_V0_TARGET_VM;
156 args.access = NV_DMA_V0_ACCESS_VM; 167 args.access = NV_DMA_V0_ACCESS_VM;
157 args.start = 0; 168 args.start = 0;
158 args.limit = cli->vm->mmu->limit - 1; 169 args.limit = cli->vmm.vmm.limit - 1;
170
171 chan->push.addr = chan->push.vma->addr;
159 } else 172 } else
160 if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) { 173 if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
161 if (device->info.family == NV_DEVICE_INFO_V0_TNT) { 174 if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
@@ -185,7 +198,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
185 args.target = NV_DMA_V0_TARGET_VM; 198 args.target = NV_DMA_V0_TARGET_VM;
186 args.access = NV_DMA_V0_ACCESS_RDWR; 199 args.access = NV_DMA_V0_ACCESS_RDWR;
187 args.start = 0; 200 args.start = 0;
188 args.limit = mmu->limit - 1; 201 args.limit = cli->vmm.vmm.limit - 1;
189 } 202 }
190 } 203 }
191 204
@@ -203,6 +216,7 @@ static int
203nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, 216nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
204 u32 engine, struct nouveau_channel **pchan) 217 u32 engine, struct nouveau_channel **pchan)
205{ 218{
219 struct nouveau_cli *cli = (void *)device->object.client;
206 static const u16 oclasses[] = { PASCAL_CHANNEL_GPFIFO_A, 220 static const u16 oclasses[] = { PASCAL_CHANNEL_GPFIFO_A,
207 MAXWELL_CHANNEL_GPFIFO_A, 221 MAXWELL_CHANNEL_GPFIFO_A,
208 KEPLER_CHANNEL_GPFIFO_B, 222 KEPLER_CHANNEL_GPFIFO_B,
@@ -233,22 +247,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
233 args.kepler.version = 0; 247 args.kepler.version = 0;
234 args.kepler.engines = engine; 248 args.kepler.engines = engine;
235 args.kepler.ilength = 0x02000; 249 args.kepler.ilength = 0x02000;
236 args.kepler.ioffset = 0x10000 + chan->push.vma.offset; 250 args.kepler.ioffset = 0x10000 + chan->push.addr;
237 args.kepler.vm = 0; 251 args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
238 size = sizeof(args.kepler); 252 size = sizeof(args.kepler);
239 } else 253 } else
240 if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { 254 if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
241 args.fermi.version = 0; 255 args.fermi.version = 0;
242 args.fermi.ilength = 0x02000; 256 args.fermi.ilength = 0x02000;
243 args.fermi.ioffset = 0x10000 + chan->push.vma.offset; 257 args.fermi.ioffset = 0x10000 + chan->push.addr;
244 args.fermi.vm = 0; 258 args.fermi.vmm = nvif_handle(&cli->vmm.vmm.object);
245 size = sizeof(args.fermi); 259 size = sizeof(args.fermi);
246 } else { 260 } else {
247 args.nv50.version = 0; 261 args.nv50.version = 0;
248 args.nv50.ilength = 0x02000; 262 args.nv50.ilength = 0x02000;
249 args.nv50.ioffset = 0x10000 + chan->push.vma.offset; 263 args.nv50.ioffset = 0x10000 + chan->push.addr;
250 args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); 264 args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
251 args.nv50.vm = 0; 265 args.nv50.vmm = nvif_handle(&cli->vmm.vmm.object);
252 size = sizeof(args.nv50); 266 size = sizeof(args.nv50);
253 } 267 }
254 268
@@ -293,7 +307,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
293 /* create channel object */ 307 /* create channel object */
294 args.version = 0; 308 args.version = 0;
295 args.pushbuf = nvif_handle(&chan->push.ctxdma); 309 args.pushbuf = nvif_handle(&chan->push.ctxdma);
296 args.offset = chan->push.vma.offset; 310 args.offset = chan->push.addr;
297 311
298 do { 312 do {
299 ret = nvif_object_init(&device->object, 0, *oclass++, 313 ret = nvif_object_init(&device->object, 0, *oclass++,
@@ -314,11 +328,10 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
314 struct nvif_device *device = chan->device; 328 struct nvif_device *device = chan->device;
315 struct nouveau_cli *cli = (void *)chan->user.client; 329 struct nouveau_cli *cli = (void *)chan->user.client;
316 struct nouveau_drm *drm = chan->drm; 330 struct nouveau_drm *drm = chan->drm;
317 struct nvkm_mmu *mmu = nvxx_mmu(device);
318 struct nv_dma_v0 args = {}; 331 struct nv_dma_v0 args = {};
319 int ret, i; 332 int ret, i;
320 333
321 nvif_object_map(&chan->user); 334 nvif_object_map(&chan->user, NULL, 0);
322 335
323 if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { 336 if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
324 ret = nvif_notify_init(&chan->user, nouveau_channel_killed, 337 ret = nvif_notify_init(&chan->user, nouveau_channel_killed,
@@ -339,7 +352,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
339 args.target = NV_DMA_V0_TARGET_VM; 352 args.target = NV_DMA_V0_TARGET_VM;
340 args.access = NV_DMA_V0_ACCESS_VM; 353 args.access = NV_DMA_V0_ACCESS_VM;
341 args.start = 0; 354 args.start = 0;
342 args.limit = cli->vm->mmu->limit - 1; 355 args.limit = cli->vmm.vmm.limit - 1;
343 } else { 356 } else {
344 args.target = NV_DMA_V0_TARGET_VRAM; 357 args.target = NV_DMA_V0_TARGET_VRAM;
345 args.access = NV_DMA_V0_ACCESS_RDWR; 358 args.access = NV_DMA_V0_ACCESS_RDWR;
@@ -356,7 +369,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
356 args.target = NV_DMA_V0_TARGET_VM; 369 args.target = NV_DMA_V0_TARGET_VM;
357 args.access = NV_DMA_V0_ACCESS_VM; 370 args.access = NV_DMA_V0_ACCESS_VM;
358 args.start = 0; 371 args.start = 0;
359 args.limit = cli->vm->mmu->limit - 1; 372 args.limit = cli->vmm.vmm.limit - 1;
360 } else 373 } else
361 if (chan->drm->agp.bridge) { 374 if (chan->drm->agp.bridge) {
362 args.target = NV_DMA_V0_TARGET_AGP; 375 args.target = NV_DMA_V0_TARGET_AGP;
@@ -368,7 +381,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
368 args.target = NV_DMA_V0_TARGET_VM; 381 args.target = NV_DMA_V0_TARGET_VM;
369 args.access = NV_DMA_V0_ACCESS_RDWR; 382 args.access = NV_DMA_V0_ACCESS_RDWR;
370 args.start = 0; 383 args.start = 0;
371 args.limit = mmu->limit - 1; 384 args.limit = cli->vmm.vmm.limit - 1;
372 } 385 }
373 386
374 ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY, 387 ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY,
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
index 46b947ba1cf4..f29d3a72c48c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
@@ -16,8 +16,9 @@ struct nouveau_channel {
16 16
17 struct { 17 struct {
18 struct nouveau_bo *buffer; 18 struct nouveau_bo *buffer;
19 struct nvkm_vma vma; 19 struct nouveau_vma *vma;
20 struct nvif_object ctxdma; 20 struct nvif_object ctxdma;
21 u64 addr;
21 } push; 22 } push;
22 23
23 /* TODO: this will be reworked in the near future */ 24 /* TODO: this will be reworked in the near future */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 201aec2ea5b8..1411bf05b89d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -1,14 +1,11 @@
1#ifndef __NOUVEAU_DISPLAY_H__ 1#ifndef __NOUVEAU_DISPLAY_H__
2#define __NOUVEAU_DISPLAY_H__ 2#define __NOUVEAU_DISPLAY_H__
3
4#include <subdev/mmu.h>
5
6#include "nouveau_drv.h" 3#include "nouveau_drv.h"
7 4
8struct nouveau_framebuffer { 5struct nouveau_framebuffer {
9 struct drm_framebuffer base; 6 struct drm_framebuffer base;
10 struct nouveau_bo *nvbo; 7 struct nouveau_bo *nvbo;
11 struct nvkm_vma vma; 8 struct nouveau_vma *vma;
12 u32 r_handle; 9 u32 r_handle;
13 u32 r_format; 10 u32 r_format;
14 u32 r_pitch; 11 u32 r_pitch;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 2634a1a79888..10e84f6ca2b7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -26,6 +26,7 @@
26 26
27#include "nouveau_drv.h" 27#include "nouveau_drv.h"
28#include "nouveau_dma.h" 28#include "nouveau_dma.h"
29#include "nouveau_vmm.h"
29 30
30void 31void
31OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) 32OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
@@ -71,11 +72,11 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
71 return -EBUSY; 72 return -EBUSY;
72 } 73 }
73 74
74 if (val < chan->push.vma.offset || 75 if (val < chan->push.addr ||
75 val > chan->push.vma.offset + (chan->dma.max << 2)) 76 val > chan->push.addr + (chan->dma.max << 2))
76 return -EINVAL; 77 return -EINVAL;
77 78
78 return (val - chan->push.vma.offset) >> 2; 79 return (val - chan->push.addr) >> 2;
79} 80}
80 81
81void 82void
@@ -84,13 +85,13 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
84{ 85{
85 struct nouveau_cli *cli = (void *)chan->user.client; 86 struct nouveau_cli *cli = (void *)chan->user.client;
86 struct nouveau_bo *pb = chan->push.buffer; 87 struct nouveau_bo *pb = chan->push.buffer;
87 struct nvkm_vma *vma; 88 struct nouveau_vma *vma;
88 int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; 89 int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
89 u64 offset; 90 u64 offset;
90 91
91 vma = nouveau_bo_vma_find(bo, cli->vm); 92 vma = nouveau_vma_find(bo, &cli->vmm);
92 BUG_ON(!vma); 93 BUG_ON(!vma);
93 offset = vma->offset + delta; 94 offset = vma->addr + delta;
94 95
95 BUG_ON(chan->dma.ib_free < 1); 96 BUG_ON(chan->dma.ib_free < 1);
96 97
@@ -224,7 +225,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
224 * instruct the GPU to jump back to the start right 225 * instruct the GPU to jump back to the start right
225 * after processing the currently pending commands. 226 * after processing the currently pending commands.
226 */ 227 */
227 OUT_RING(chan, chan->push.vma.offset | 0x20000000); 228 OUT_RING(chan, chan->push.addr | 0x20000000);
228 229
229 /* wait for GET to depart from the skips area. 230 /* wait for GET to depart from the skips area.
230 * prevents writing GET==PUT and causing a race 231 * prevents writing GET==PUT and causing a race
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index aff3a9d0a1fc..74e10b14a7da 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -140,7 +140,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data)
140#define WRITE_PUT(val) do { \ 140#define WRITE_PUT(val) do { \
141 mb(); \ 141 mb(); \
142 nouveau_bo_rd32(chan->push.buffer, 0); \ 142 nouveau_bo_rd32(chan->push.buffer, 0); \
143 nvif_wr32(&chan->user, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ 143 nvif_wr32(&chan->user, chan->user_put, ((val) << 2) + chan->push.addr);\
144} while (0) 144} while (0)
145 145
146static inline void 146static inline void
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 595630d1fb9e..8d4a5be3b913 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -111,33 +111,119 @@ nouveau_name(struct drm_device *dev)
111 return nouveau_platform_name(to_platform_device(dev->dev)); 111 return nouveau_platform_name(to_platform_device(dev->dev));
112} 112}
113 113
114static inline bool
115nouveau_cli_work_ready(struct dma_fence *fence, bool wait)
116{
117 if (!dma_fence_is_signaled(fence)) {
118 if (!wait)
119 return false;
120 WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0);
121 }
122 dma_fence_put(fence);
123 return true;
124}
125
126static void
127nouveau_cli_work_flush(struct nouveau_cli *cli, bool wait)
128{
129 struct nouveau_cli_work *work, *wtmp;
130 mutex_lock(&cli->lock);
131 list_for_each_entry_safe(work, wtmp, &cli->worker, head) {
132 if (!work->fence || nouveau_cli_work_ready(work->fence, wait)) {
133 list_del(&work->head);
134 work->func(work);
135 }
136 }
137 mutex_unlock(&cli->lock);
138}
139
140static void
141nouveau_cli_work_fence(struct dma_fence *fence, struct dma_fence_cb *cb)
142{
143 struct nouveau_cli_work *work = container_of(cb, typeof(*work), cb);
144 schedule_work(&work->cli->work);
145}
146
147void
148nouveau_cli_work_queue(struct nouveau_cli *cli, struct dma_fence *fence,
149 struct nouveau_cli_work *work)
150{
151 work->fence = dma_fence_get(fence);
152 work->cli = cli;
153 mutex_lock(&cli->lock);
154 list_add_tail(&work->head, &cli->worker);
155 mutex_unlock(&cli->lock);
156 if (dma_fence_add_callback(fence, &work->cb, nouveau_cli_work_fence))
157 nouveau_cli_work_fence(fence, &work->cb);
158}
159
160static void
161nouveau_cli_work(struct work_struct *w)
162{
163 struct nouveau_cli *cli = container_of(w, typeof(*cli), work);
164 nouveau_cli_work_flush(cli, false);
165}
166
114static void 167static void
115nouveau_cli_fini(struct nouveau_cli *cli) 168nouveau_cli_fini(struct nouveau_cli *cli)
116{ 169{
117 nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); 170 nouveau_cli_work_flush(cli, true);
118 usif_client_fini(cli); 171 usif_client_fini(cli);
172 nouveau_vmm_fini(&cli->vmm);
173 nvif_mmu_fini(&cli->mmu);
119 nvif_device_fini(&cli->device); 174 nvif_device_fini(&cli->device);
175 mutex_lock(&cli->drm->master.lock);
120 nvif_client_fini(&cli->base); 176 nvif_client_fini(&cli->base);
177 mutex_unlock(&cli->drm->master.lock);
121} 178}
122 179
123static int 180static int
124nouveau_cli_init(struct nouveau_drm *drm, const char *sname, 181nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
125 struct nouveau_cli *cli) 182 struct nouveau_cli *cli)
126{ 183{
184 static const struct nvif_mclass
185 mems[] = {
186 { NVIF_CLASS_MEM_GF100, -1 },
187 { NVIF_CLASS_MEM_NV50 , -1 },
188 { NVIF_CLASS_MEM_NV04 , -1 },
189 {}
190 };
191 static const struct nvif_mclass
192 mmus[] = {
193 { NVIF_CLASS_MMU_GF100, -1 },
194 { NVIF_CLASS_MMU_NV50 , -1 },
195 { NVIF_CLASS_MMU_NV04 , -1 },
196 {}
197 };
198 static const struct nvif_mclass
199 vmms[] = {
200 { NVIF_CLASS_VMM_GP100, -1 },
201 { NVIF_CLASS_VMM_GM200, -1 },
202 { NVIF_CLASS_VMM_GF100, -1 },
203 { NVIF_CLASS_VMM_NV50 , -1 },
204 { NVIF_CLASS_VMM_NV04 , -1 },
205 {}
206 };
127 u64 device = nouveau_name(drm->dev); 207 u64 device = nouveau_name(drm->dev);
128 int ret; 208 int ret;
129 209
130 snprintf(cli->name, sizeof(cli->name), "%s", sname); 210 snprintf(cli->name, sizeof(cli->name), "%s", sname);
131 cli->dev = drm->dev; 211 cli->drm = drm;
132 mutex_init(&cli->mutex); 212 mutex_init(&cli->mutex);
133 usif_client_init(cli); 213 usif_client_init(cli);
134 214
135 if (cli == &drm->client) { 215 INIT_WORK(&cli->work, nouveau_cli_work);
216 INIT_LIST_HEAD(&cli->worker);
217 mutex_init(&cli->lock);
218
219 if (cli == &drm->master) {
136 ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, 220 ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug,
137 cli->name, device, &cli->base); 221 cli->name, device, &cli->base);
138 } else { 222 } else {
139 ret = nvif_client_init(&drm->client.base, cli->name, device, 223 mutex_lock(&drm->master.lock);
224 ret = nvif_client_init(&drm->master.base, cli->name, device,
140 &cli->base); 225 &cli->base);
226 mutex_unlock(&drm->master.lock);
141 } 227 }
142 if (ret) { 228 if (ret) {
143 NV_ERROR(drm, "Client allocation failed: %d\n", ret); 229 NV_ERROR(drm, "Client allocation failed: %d\n", ret);
@@ -154,6 +240,38 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
154 goto done; 240 goto done;
155 } 241 }
156 242
243 ret = nvif_mclass(&cli->device.object, mmus);
244 if (ret < 0) {
245 NV_ERROR(drm, "No supported MMU class\n");
246 goto done;
247 }
248
249 ret = nvif_mmu_init(&cli->device.object, mmus[ret].oclass, &cli->mmu);
250 if (ret) {
251 NV_ERROR(drm, "MMU allocation failed: %d\n", ret);
252 goto done;
253 }
254
255 ret = nvif_mclass(&cli->mmu.object, vmms);
256 if (ret < 0) {
257 NV_ERROR(drm, "No supported VMM class\n");
258 goto done;
259 }
260
261 ret = nouveau_vmm_init(cli, vmms[ret].oclass, &cli->vmm);
262 if (ret) {
263 NV_ERROR(drm, "VMM allocation failed: %d\n", ret);
264 goto done;
265 }
266
267 ret = nvif_mclass(&cli->mmu.object, mems);
268 if (ret < 0) {
269 NV_ERROR(drm, "No supported MEM class\n");
270 goto done;
271 }
272
273 cli->mem = &mems[ret];
274 return 0;
157done: 275done:
158 if (ret) 276 if (ret)
159 nouveau_cli_fini(cli); 277 nouveau_cli_fini(cli);
@@ -433,6 +551,10 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
433 dev->dev_private = drm; 551 dev->dev_private = drm;
434 drm->dev = dev; 552 drm->dev = dev;
435 553
554 ret = nouveau_cli_init(drm, "DRM-master", &drm->master);
555 if (ret)
556 return ret;
557
436 ret = nouveau_cli_init(drm, "DRM", &drm->client); 558 ret = nouveau_cli_init(drm, "DRM", &drm->client);
437 if (ret) 559 if (ret)
438 return ret; 560 return ret;
@@ -456,21 +578,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
456 578
457 nouveau_vga_init(drm); 579 nouveau_vga_init(drm);
458 580
459 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
460 if (!nvxx_device(&drm->client.device)->mmu) {
461 ret = -ENOSYS;
462 goto fail_device;
463 }
464
465 ret = nvkm_vm_new(nvxx_device(&drm->client.device),
466 0, (1ULL << 40), 0x1000, NULL,
467 &drm->client.vm);
468 if (ret)
469 goto fail_device;
470
471 nvxx_client(&drm->client.base)->vm = drm->client.vm;
472 }
473
474 ret = nouveau_ttm_init(drm); 581 ret = nouveau_ttm_init(drm);
475 if (ret) 582 if (ret)
476 goto fail_ttm; 583 goto fail_ttm;
@@ -516,8 +623,8 @@ fail_bios:
516 nouveau_ttm_fini(drm); 623 nouveau_ttm_fini(drm);
517fail_ttm: 624fail_ttm:
518 nouveau_vga_fini(drm); 625 nouveau_vga_fini(drm);
519fail_device:
520 nouveau_cli_fini(&drm->client); 626 nouveau_cli_fini(&drm->client);
627 nouveau_cli_fini(&drm->master);
521 kfree(drm); 628 kfree(drm);
522 return ret; 629 return ret;
523} 630}
@@ -550,6 +657,7 @@ nouveau_drm_unload(struct drm_device *dev)
550 if (drm->hdmi_device) 657 if (drm->hdmi_device)
551 pci_dev_put(drm->hdmi_device); 658 pci_dev_put(drm->hdmi_device);
552 nouveau_cli_fini(&drm->client); 659 nouveau_cli_fini(&drm->client);
660 nouveau_cli_fini(&drm->master);
553 kfree(drm); 661 kfree(drm);
554} 662}
555 663
@@ -618,7 +726,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
618 } 726 }
619 727
620 NV_DEBUG(drm, "suspending object tree...\n"); 728 NV_DEBUG(drm, "suspending object tree...\n");
621 ret = nvif_client_suspend(&drm->client.base); 729 ret = nvif_client_suspend(&drm->master.base);
622 if (ret) 730 if (ret)
623 goto fail_client; 731 goto fail_client;
624 732
@@ -642,7 +750,7 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
642 struct nouveau_drm *drm = nouveau_drm(dev); 750 struct nouveau_drm *drm = nouveau_drm(dev);
643 751
644 NV_DEBUG(drm, "resuming object tree...\n"); 752 NV_DEBUG(drm, "resuming object tree...\n");
645 nvif_client_resume(&drm->client.base); 753 nvif_client_resume(&drm->master.base);
646 754
647 NV_DEBUG(drm, "resuming fence...\n"); 755 NV_DEBUG(drm, "resuming fence...\n");
648 if (drm->fence && nouveau_fence(drm)->resume) 756 if (drm->fence && nouveau_fence(drm)->resume)
@@ -850,15 +958,6 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
850 958
851 cli->base.super = false; 959 cli->base.super = false;
852 960
853 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
854 ret = nvkm_vm_new(nvxx_device(&drm->client.device), 0,
855 (1ULL << 40), 0x1000, NULL, &cli->vm);
856 if (ret)
857 goto done;
858
859 nvxx_client(&cli->base)->vm = cli->vm;
860 }
861
862 fpriv->driver_priv = cli; 961 fpriv->driver_priv = cli;
863 962
864 mutex_lock(&drm->client.mutex); 963 mutex_lock(&drm->client.mutex);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 822fe1d4d35e..e86b8220a4bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -5,7 +5,7 @@
5#define DRIVER_EMAIL "nouveau@lists.freedesktop.org" 5#define DRIVER_EMAIL "nouveau@lists.freedesktop.org"
6 6
7#define DRIVER_NAME "nouveau" 7#define DRIVER_NAME "nouveau"
8#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla" 8#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla/Tegra K1+"
9#define DRIVER_DATE "20120801" 9#define DRIVER_DATE "20120801"
10 10
11#define DRIVER_MAJOR 1 11#define DRIVER_MAJOR 1
@@ -42,6 +42,8 @@
42#include <nvif/client.h> 42#include <nvif/client.h>
43#include <nvif/device.h> 43#include <nvif/device.h>
44#include <nvif/ioctl.h> 44#include <nvif/ioctl.h>
45#include <nvif/mmu.h>
46#include <nvif/vmm.h>
45 47
46#include <drm/drmP.h> 48#include <drm/drmP.h>
47 49
@@ -61,6 +63,7 @@ struct platform_device;
61 63
62#include "nouveau_fence.h" 64#include "nouveau_fence.h"
63#include "nouveau_bios.h" 65#include "nouveau_bios.h"
66#include "nouveau_vmm.h"
64 67
65struct nouveau_drm_tile { 68struct nouveau_drm_tile {
66 struct nouveau_fence *fence; 69 struct nouveau_fence *fence;
@@ -86,19 +89,37 @@ enum nouveau_drm_handle {
86 89
87struct nouveau_cli { 90struct nouveau_cli {
88 struct nvif_client base; 91 struct nvif_client base;
89 struct drm_device *dev; 92 struct nouveau_drm *drm;
90 struct mutex mutex; 93 struct mutex mutex;
91 94
92 struct nvif_device device; 95 struct nvif_device device;
96 struct nvif_mmu mmu;
97 struct nouveau_vmm vmm;
98 const struct nvif_mclass *mem;
93 99
94 struct nvkm_vm *vm; /*XXX*/
95 struct list_head head; 100 struct list_head head;
96 void *abi16; 101 void *abi16;
97 struct list_head objects; 102 struct list_head objects;
98 struct list_head notifys; 103 struct list_head notifys;
99 char name[32]; 104 char name[32];
105
106 struct work_struct work;
107 struct list_head worker;
108 struct mutex lock;
100}; 109};
101 110
111struct nouveau_cli_work {
112 void (*func)(struct nouveau_cli_work *);
113 struct nouveau_cli *cli;
114 struct list_head head;
115
116 struct dma_fence *fence;
117 struct dma_fence_cb cb;
118};
119
120void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *,
121 struct nouveau_cli_work *);
122
102static inline struct nouveau_cli * 123static inline struct nouveau_cli *
103nouveau_cli(struct drm_file *fpriv) 124nouveau_cli(struct drm_file *fpriv)
104{ 125{
@@ -109,6 +130,7 @@ nouveau_cli(struct drm_file *fpriv)
109#include <nvif/device.h> 130#include <nvif/device.h>
110 131
111struct nouveau_drm { 132struct nouveau_drm {
133 struct nouveau_cli master;
112 struct nouveau_cli client; 134 struct nouveau_cli client;
113 struct drm_device *dev; 135 struct drm_device *dev;
114 136
@@ -133,6 +155,9 @@ struct nouveau_drm {
133 struct nouveau_channel *chan; 155 struct nouveau_channel *chan;
134 struct nvif_object copy; 156 struct nvif_object copy;
135 int mtrr; 157 int mtrr;
158 int type_vram;
159 int type_host;
160 int type_ncoh;
136 } ttm; 161 } ttm;
137 162
138 /* GEM interface support */ 163 /* GEM interface support */
@@ -204,7 +229,7 @@ void nouveau_drm_device_remove(struct drm_device *dev);
204 229
205#define NV_PRINTK(l,c,f,a...) do { \ 230#define NV_PRINTK(l,c,f,a...) do { \
206 struct nouveau_cli *_cli = (c); \ 231 struct nouveau_cli *_cli = (c); \
207 dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a); \ 232 dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \
208} while(0) 233} while(0)
209#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) 234#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
210#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) 235#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 2b12d82aac15..c533d8e04afc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -48,6 +48,7 @@
48#include "nouveau_bo.h" 48#include "nouveau_bo.h"
49#include "nouveau_fbcon.h" 49#include "nouveau_fbcon.h"
50#include "nouveau_chan.h" 50#include "nouveau_chan.h"
51#include "nouveau_vmm.h"
51 52
52#include "nouveau_crtc.h" 53#include "nouveau_crtc.h"
53 54
@@ -348,7 +349,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
348 349
349 chan = nouveau_nofbaccel ? NULL : drm->channel; 350 chan = nouveau_nofbaccel ? NULL : drm->channel;
350 if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) { 351 if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
351 ret = nouveau_bo_vma_add(nvbo, drm->client.vm, &fb->vma); 352 ret = nouveau_vma_new(nvbo, &drm->client.vmm, &fb->vma);
352 if (ret) { 353 if (ret) {
353 NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); 354 NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
354 chan = NULL; 355 chan = NULL;
@@ -402,7 +403,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
402 403
403out_unlock: 404out_unlock:
404 if (chan) 405 if (chan)
405 nouveau_bo_vma_del(fb->nvbo, &fb->vma); 406 nouveau_vma_del(&fb->vma);
406 nouveau_bo_unmap(fb->nvbo); 407 nouveau_bo_unmap(fb->nvbo);
407out_unpin: 408out_unpin:
408 nouveau_bo_unpin(fb->nvbo); 409 nouveau_bo_unpin(fb->nvbo);
@@ -429,7 +430,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
429 drm_fb_helper_fini(&fbcon->helper); 430 drm_fb_helper_fini(&fbcon->helper);
430 431
431 if (nouveau_fb->nvbo) { 432 if (nouveau_fb->nvbo) {
432 nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma); 433 nouveau_vma_del(&nouveau_fb->vma);
433 nouveau_bo_unmap(nouveau_fb->nvbo); 434 nouveau_bo_unmap(nouveau_fb->nvbo);
434 nouveau_bo_unpin(nouveau_fb->nvbo); 435 nouveau_bo_unpin(nouveau_fb->nvbo);
435 drm_framebuffer_unreference(&nouveau_fb->base); 436 drm_framebuffer_unreference(&nouveau_fb->base);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 99e14e3e0fe4..503fa94dc06d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -199,62 +199,6 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
199 WARN_ON(ret); 199 WARN_ON(ret);
200} 200}
201 201
202struct nouveau_fence_work {
203 struct work_struct work;
204 struct dma_fence_cb cb;
205 void (*func)(void *);
206 void *data;
207};
208
209static void
210nouveau_fence_work_handler(struct work_struct *kwork)
211{
212 struct nouveau_fence_work *work = container_of(kwork, typeof(*work), work);
213 work->func(work->data);
214 kfree(work);
215}
216
217static void nouveau_fence_work_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
218{
219 struct nouveau_fence_work *work = container_of(cb, typeof(*work), cb);
220
221 schedule_work(&work->work);
222}
223
224void
225nouveau_fence_work(struct dma_fence *fence,
226 void (*func)(void *), void *data)
227{
228 struct nouveau_fence_work *work;
229
230 if (dma_fence_is_signaled(fence))
231 goto err;
232
233 work = kmalloc(sizeof(*work), GFP_KERNEL);
234 if (!work) {
235 /*
236 * this might not be a nouveau fence any more,
237 * so force a lazy wait here
238 */
239 WARN_ON(nouveau_fence_wait((struct nouveau_fence *)fence,
240 true, false));
241 goto err;
242 }
243
244 INIT_WORK(&work->work, nouveau_fence_work_handler);
245 work->func = func;
246 work->data = data;
247
248 if (dma_fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0)
249 goto err_free;
250 return;
251
252err_free:
253 kfree(work);
254err:
255 func(data);
256}
257
258int 202int
259nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) 203nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
260{ 204{
@@ -474,8 +418,6 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
474 if (!fence) 418 if (!fence)
475 return -ENOMEM; 419 return -ENOMEM;
476 420
477 fence->sysmem = sysmem;
478
479 ret = nouveau_fence_emit(fence, chan); 421 ret = nouveau_fence_emit(fence, chan);
480 if (ret) 422 if (ret)
481 nouveau_fence_unref(&fence); 423 nouveau_fence_unref(&fence);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index d5e58a38f160..c36031aa013e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -12,8 +12,6 @@ struct nouveau_fence {
12 12
13 struct list_head head; 13 struct list_head head;
14 14
15 bool sysmem;
16
17 struct nouveau_channel __rcu *channel; 15 struct nouveau_channel __rcu *channel;
18 unsigned long timeout; 16 unsigned long timeout;
19}; 17};
@@ -24,7 +22,6 @@ void nouveau_fence_unref(struct nouveau_fence **);
24 22
25int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); 23int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
26bool nouveau_fence_done(struct nouveau_fence *); 24bool nouveau_fence_done(struct nouveau_fence *);
27void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *);
28int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); 25int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
29int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); 26int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
30 27
@@ -90,14 +87,12 @@ int nouveau_flip_complete(struct nvif_notify *);
90 87
91struct nv84_fence_chan { 88struct nv84_fence_chan {
92 struct nouveau_fence_chan base; 89 struct nouveau_fence_chan base;
93 struct nvkm_vma vma; 90 struct nouveau_vma *vma;
94 struct nvkm_vma vma_gart;
95}; 91};
96 92
97struct nv84_fence_priv { 93struct nv84_fence_priv {
98 struct nouveau_fence_priv base; 94 struct nouveau_fence_priv base;
99 struct nouveau_bo *bo; 95 struct nouveau_bo *bo;
100 struct nouveau_bo *bo_gart;
101 u32 *suspend; 96 u32 *suspend;
102 struct mutex mutex; 97 struct mutex mutex;
103}; 98};
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 2170534101ca..efc89aaef66a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -31,6 +31,10 @@
31 31
32#include "nouveau_ttm.h" 32#include "nouveau_ttm.h"
33#include "nouveau_gem.h" 33#include "nouveau_gem.h"
34#include "nouveau_mem.h"
35#include "nouveau_vmm.h"
36
37#include <nvif/class.h>
34 38
35void 39void
36nouveau_gem_object_del(struct drm_gem_object *gem) 40nouveau_gem_object_del(struct drm_gem_object *gem)
@@ -64,66 +68,61 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
64 struct nouveau_cli *cli = nouveau_cli(file_priv); 68 struct nouveau_cli *cli = nouveau_cli(file_priv);
65 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 69 struct nouveau_bo *nvbo = nouveau_gem_object(gem);
66 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 70 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
67 struct nvkm_vma *vma;
68 struct device *dev = drm->dev->dev; 71 struct device *dev = drm->dev->dev;
72 struct nouveau_vma *vma;
69 int ret; 73 int ret;
70 74
71 if (!cli->vm) 75 if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50)
72 return 0; 76 return 0;
73 77
74 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); 78 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
75 if (ret) 79 if (ret)
76 return ret; 80 return ret;
77 81
78 vma = nouveau_bo_vma_find(nvbo, cli->vm); 82 ret = pm_runtime_get_sync(dev);
79 if (!vma) { 83 if (ret < 0 && ret != -EACCES)
80 vma = kzalloc(sizeof(*vma), GFP_KERNEL); 84 goto out;
81 if (!vma) {
82 ret = -ENOMEM;
83 goto out;
84 }
85
86 ret = pm_runtime_get_sync(dev);
87 if (ret < 0 && ret != -EACCES) {
88 kfree(vma);
89 goto out;
90 }
91
92 ret = nouveau_bo_vma_add(nvbo, cli->vm, vma);
93 if (ret)
94 kfree(vma);
95
96 pm_runtime_mark_last_busy(dev);
97 pm_runtime_put_autosuspend(dev);
98 } else {
99 vma->refcount++;
100 }
101 85
86 ret = nouveau_vma_new(nvbo, &cli->vmm, &vma);
87 pm_runtime_mark_last_busy(dev);
88 pm_runtime_put_autosuspend(dev);
102out: 89out:
103 ttm_bo_unreserve(&nvbo->bo); 90 ttm_bo_unreserve(&nvbo->bo);
104 return ret; 91 return ret;
105} 92}
106 93
94struct nouveau_gem_object_unmap {
95 struct nouveau_cli_work work;
96 struct nouveau_vma *vma;
97};
98
107static void 99static void
108nouveau_gem_object_delete(void *data) 100nouveau_gem_object_delete(struct nouveau_vma *vma)
109{ 101{
110 struct nvkm_vma *vma = data; 102 nouveau_vma_del(&vma);
111 nvkm_vm_unmap(vma);
112 nvkm_vm_put(vma);
113 kfree(vma);
114} 103}
115 104
116static void 105static void
117nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma) 106nouveau_gem_object_delete_work(struct nouveau_cli_work *w)
107{
108 struct nouveau_gem_object_unmap *work =
109 container_of(w, typeof(*work), work);
110 nouveau_gem_object_delete(work->vma);
111 kfree(work);
112}
113
114static void
115nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
118{ 116{
119 const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM; 117 const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM;
120 struct reservation_object *resv = nvbo->bo.resv; 118 struct reservation_object *resv = nvbo->bo.resv;
121 struct reservation_object_list *fobj; 119 struct reservation_object_list *fobj;
120 struct nouveau_gem_object_unmap *work;
122 struct dma_fence *fence = NULL; 121 struct dma_fence *fence = NULL;
123 122
124 fobj = reservation_object_get_list(resv); 123 fobj = reservation_object_get_list(resv);
125 124
126 list_del(&vma->head); 125 list_del_init(&vma->head);
127 126
128 if (fobj && fobj->shared_count > 1) 127 if (fobj && fobj->shared_count > 1)
129 ttm_bo_wait(&nvbo->bo, false, false); 128 ttm_bo_wait(&nvbo->bo, false, false);
@@ -133,14 +132,20 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma)
133 else 132 else
134 fence = reservation_object_get_excl(nvbo->bo.resv); 133 fence = reservation_object_get_excl(nvbo->bo.resv);
135 134
136 if (fence && mapped) { 135 if (!fence || !mapped) {
137 nouveau_fence_work(fence, nouveau_gem_object_delete, vma); 136 nouveau_gem_object_delete(vma);
138 } else { 137 return;
139 if (mapped) 138 }
140 nvkm_vm_unmap(vma); 139
141 nvkm_vm_put(vma); 140 if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) {
142 kfree(vma); 141 WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0);
142 nouveau_gem_object_delete(vma);
143 return;
143 } 144 }
145
146 work->work.func = nouveau_gem_object_delete_work;
147 work->vma = vma;
148 nouveau_cli_work_queue(vma->vmm->cli, fence, &work->work);
144} 149}
145 150
146void 151void
@@ -150,19 +155,19 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
150 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 155 struct nouveau_bo *nvbo = nouveau_gem_object(gem);
151 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 156 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
152 struct device *dev = drm->dev->dev; 157 struct device *dev = drm->dev->dev;
153 struct nvkm_vma *vma; 158 struct nouveau_vma *vma;
154 int ret; 159 int ret;
155 160
156 if (!cli->vm) 161 if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50)
157 return; 162 return;
158 163
159 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); 164 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
160 if (ret) 165 if (ret)
161 return; 166 return;
162 167
163 vma = nouveau_bo_vma_find(nvbo, cli->vm); 168 vma = nouveau_vma_find(nvbo, &cli->vmm);
164 if (vma) { 169 if (vma) {
165 if (--vma->refcount == 0) { 170 if (--vma->refs == 0) {
166 ret = pm_runtime_get_sync(dev); 171 ret = pm_runtime_get_sync(dev);
167 if (!WARN_ON(ret < 0 && ret != -EACCES)) { 172 if (!WARN_ON(ret < 0 && ret != -EACCES)) {
168 nouveau_gem_object_unmap(nvbo, vma); 173 nouveau_gem_object_unmap(nvbo, vma);
@@ -179,7 +184,7 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
179 uint32_t tile_mode, uint32_t tile_flags, 184 uint32_t tile_mode, uint32_t tile_flags,
180 struct nouveau_bo **pnvbo) 185 struct nouveau_bo **pnvbo)
181{ 186{
182 struct nouveau_drm *drm = nouveau_drm(cli->dev); 187 struct nouveau_drm *drm = cli->drm;
183 struct nouveau_bo *nvbo; 188 struct nouveau_bo *nvbo;
184 u32 flags = 0; 189 u32 flags = 0;
185 int ret; 190 int ret;
@@ -227,7 +232,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
227{ 232{
228 struct nouveau_cli *cli = nouveau_cli(file_priv); 233 struct nouveau_cli *cli = nouveau_cli(file_priv);
229 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 234 struct nouveau_bo *nvbo = nouveau_gem_object(gem);
230 struct nvkm_vma *vma; 235 struct nouveau_vma *vma;
231 236
232 if (is_power_of_2(nvbo->valid_domains)) 237 if (is_power_of_2(nvbo->valid_domains))
233 rep->domain = nvbo->valid_domains; 238 rep->domain = nvbo->valid_domains;
@@ -236,18 +241,25 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
236 else 241 else
237 rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; 242 rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
238 rep->offset = nvbo->bo.offset; 243 rep->offset = nvbo->bo.offset;
239 if (cli->vm) { 244 if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
240 vma = nouveau_bo_vma_find(nvbo, cli->vm); 245 vma = nouveau_vma_find(nvbo, &cli->vmm);
241 if (!vma) 246 if (!vma)
242 return -EINVAL; 247 return -EINVAL;
243 248
244 rep->offset = vma->offset; 249 rep->offset = vma->addr;
245 } 250 }
246 251
247 rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; 252 rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
248 rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node); 253 rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node);
249 rep->tile_mode = nvbo->tile_mode; 254 rep->tile_mode = nvbo->mode;
250 rep->tile_flags = nvbo->tile_flags; 255 rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG;
256 if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
257 rep->tile_flags |= nvbo->kind << 8;
258 else
259 if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
260 rep->tile_flags |= nvbo->kind << 8 | nvbo->comp << 16;
261 else
262 rep->tile_flags |= nvbo->zeta;
251 return 0; 263 return 0;
252} 264}
253 265
@@ -255,18 +267,11 @@ int
255nouveau_gem_ioctl_new(struct drm_device *dev, void *data, 267nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
256 struct drm_file *file_priv) 268 struct drm_file *file_priv)
257{ 269{
258 struct nouveau_drm *drm = nouveau_drm(dev);
259 struct nouveau_cli *cli = nouveau_cli(file_priv); 270 struct nouveau_cli *cli = nouveau_cli(file_priv);
260 struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
261 struct drm_nouveau_gem_new *req = data; 271 struct drm_nouveau_gem_new *req = data;
262 struct nouveau_bo *nvbo = NULL; 272 struct nouveau_bo *nvbo = NULL;
263 int ret = 0; 273 int ret = 0;
264 274
265 if (!nvkm_fb_memtype_valid(fb, req->info.tile_flags)) {
266 NV_PRINTK(err, cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
267 return -EINVAL;
268 }
269
270 ret = nouveau_gem_new(cli, req->info.size, req->align, 275 ret = nouveau_gem_new(cli, req->info.size, req->align,
271 req->info.domain, req->info.tile_mode, 276 req->info.domain, req->info.tile_mode,
272 req->info.tile_flags, &nvbo); 277 req->info.tile_flags, &nvbo);
@@ -791,7 +796,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
791 bo[push[i].bo_index].user_priv; 796 bo[push[i].bo_index].user_priv;
792 uint32_t cmd; 797 uint32_t cmd;
793 798
794 cmd = chan->push.vma.offset + ((chan->dma.cur + 2) << 2); 799 cmd = chan->push.addr + ((chan->dma.cur + 2) << 2);
795 cmd |= 0x20000000; 800 cmd |= 0x20000000;
796 if (unlikely(cmd != req->suffix0)) { 801 if (unlikely(cmd != req->suffix0)) {
797 if (!nvbo->kmap.virtual) { 802 if (!nvbo->kmap.virtual) {
@@ -843,7 +848,7 @@ out_next:
843 req->suffix1 = 0x00000000; 848 req->suffix1 = 0x00000000;
844 } else { 849 } else {
845 req->suffix0 = 0x20000000 | 850 req->suffix0 = 0x20000000 |
846 (chan->push.vma.offset + ((chan->dma.cur + 2) << 2)); 851 (chan->push.addr + ((chan->dma.cur + 2) << 2));
847 req->suffix1 = 0x00000000; 852 req->suffix1 = 0x00000000;
848 } 853 }
849 854
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h
index 8fa6ed9ddd3a..d39f845dda87 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.h
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.h
@@ -6,9 +6,6 @@
6#include "nouveau_drv.h" 6#include "nouveau_drv.h"
7#include "nouveau_bo.h" 7#include "nouveau_bo.h"
8 8
9#define nouveau_bo_tile_layout(nvbo) \
10 ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)
11
12static inline struct nouveau_bo * 9static inline struct nouveau_bo *
13nouveau_gem_object(struct drm_gem_object *gem) 10nouveau_gem_object(struct drm_gem_object *gem)
14{ 11{
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
new file mode 100644
index 000000000000..589a9621db76
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -0,0 +1,198 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "nouveau_mem.h"
23#include "nouveau_drv.h"
24#include "nouveau_bo.h"
25
26#include <drm/ttm/ttm_bo_driver.h>
27
28#include <nvif/class.h>
29#include <nvif/if000a.h>
30#include <nvif/if500b.h>
31#include <nvif/if500d.h>
32#include <nvif/if900b.h>
33#include <nvif/if900d.h>
34
35int
36nouveau_mem_map(struct nouveau_mem *mem,
37 struct nvif_vmm *vmm, struct nvif_vma *vma)
38{
39 union {
40 struct nv50_vmm_map_v0 nv50;
41 struct gf100_vmm_map_v0 gf100;
42 } args;
43 u32 argc = 0;
44 bool super;
45 int ret;
46
47 switch (vmm->object.oclass) {
48 case NVIF_CLASS_VMM_NV04:
49 break;
50 case NVIF_CLASS_VMM_NV50:
51 args.nv50.version = 0;
52 args.nv50.ro = 0;
53 args.nv50.priv = 0;
54 args.nv50.kind = mem->kind;
55 args.nv50.comp = mem->comp;
56 argc = sizeof(args.nv50);
57 break;
58 case NVIF_CLASS_VMM_GF100:
59 case NVIF_CLASS_VMM_GM200:
60 case NVIF_CLASS_VMM_GP100:
61 args.gf100.version = 0;
62 if (mem->mem.type & NVIF_MEM_VRAM)
63 args.gf100.vol = 0;
64 else
65 args.gf100.vol = 1;
66 args.gf100.ro = 0;
67 args.gf100.priv = 0;
68 args.gf100.kind = mem->kind;
69 argc = sizeof(args.gf100);
70 break;
71 default:
72 WARN_ON(1);
73 return -ENOSYS;
74 }
75
76 super = vmm->object.client->super;
77 vmm->object.client->super = true;
78 ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc,
79 &mem->mem, 0);
80 vmm->object.client->super = super;
81 return ret;
82}
83
84void
85nouveau_mem_fini(struct nouveau_mem *mem)
86{
87 nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[1]);
88 nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[0]);
89 mutex_lock(&mem->cli->drm->master.lock);
90 nvif_mem_fini(&mem->mem);
91 mutex_unlock(&mem->cli->drm->master.lock);
92}
93
94int
95nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt)
96{
97 struct nouveau_mem *mem = nouveau_mem(reg);
98 struct nouveau_cli *cli = mem->cli;
99 struct nouveau_drm *drm = cli->drm;
100 struct nvif_mmu *mmu = &cli->mmu;
101 struct nvif_mem_ram_v0 args = {};
102 bool super = cli->base.super;
103 u8 type;
104 int ret;
105
106 if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED)
107 type = drm->ttm.type_ncoh;
108 else
109 type = drm->ttm.type_host;
110
111 if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND))
112 mem->comp = mem->kind = 0;
113 if (mem->comp && !(mmu->type[type].type & NVIF_MEM_COMP)) {
114 if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100)
115 mem->kind = mmu->kind[mem->kind];
116 mem->comp = 0;
117 }
118
119 if (tt->ttm.sg) args.sgl = tt->ttm.sg->sgl;
120 else args.dma = tt->dma_address;
121
122 mutex_lock(&drm->master.lock);
123 cli->base.super = true;
124 ret = nvif_mem_init_type(mmu, cli->mem->oclass, type, PAGE_SHIFT,
125 reg->num_pages << PAGE_SHIFT,
126 &args, sizeof(args), &mem->mem);
127 cli->base.super = super;
128 mutex_unlock(&drm->master.lock);
129 return ret;
130}
131
132int
133nouveau_mem_vram(struct ttm_mem_reg *reg, bool contig, u8 page)
134{
135 struct nouveau_mem *mem = nouveau_mem(reg);
136 struct nouveau_cli *cli = mem->cli;
137 struct nouveau_drm *drm = cli->drm;
138 struct nvif_mmu *mmu = &cli->mmu;
139 bool super = cli->base.super;
140 u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page);
141 int ret;
142
143 mutex_lock(&drm->master.lock);
144 cli->base.super = true;
145 switch (cli->mem->oclass) {
146 case NVIF_CLASS_MEM_GF100:
147 ret = nvif_mem_init_type(mmu, cli->mem->oclass,
148 drm->ttm.type_vram, page, size,
149 &(struct gf100_mem_v0) {
150 .contig = contig,
151 }, sizeof(struct gf100_mem_v0),
152 &mem->mem);
153 break;
154 case NVIF_CLASS_MEM_NV50:
155 ret = nvif_mem_init_type(mmu, cli->mem->oclass,
156 drm->ttm.type_vram, page, size,
157 &(struct nv50_mem_v0) {
158 .bankswz = mmu->kind[mem->kind] == 2,
159 .contig = contig,
160 }, sizeof(struct nv50_mem_v0),
161 &mem->mem);
162 break;
163 default:
164 ret = -ENOSYS;
165 WARN_ON(1);
166 break;
167 }
168 cli->base.super = super;
169 mutex_unlock(&drm->master.lock);
170
171 reg->start = mem->mem.addr >> PAGE_SHIFT;
172 return ret;
173}
174
175void
176nouveau_mem_del(struct ttm_mem_reg *reg)
177{
178 struct nouveau_mem *mem = nouveau_mem(reg);
179 nouveau_mem_fini(mem);
180 kfree(reg->mm_node);
181 reg->mm_node = NULL;
182}
183
184int
185nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp,
186 struct ttm_mem_reg *reg)
187{
188 struct nouveau_mem *mem;
189
190 if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL)))
191 return -ENOMEM;
192 mem->cli = cli;
193 mem->kind = kind;
194 mem->comp = comp;
195
196 reg->mm_node = mem;
197 return 0;
198}
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h
new file mode 100644
index 000000000000..f6d039e73812
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.h
@@ -0,0 +1,30 @@
1#ifndef __NOUVEAU_MEM_H__
2#define __NOUVEAU_MEM_H__
3#include <drm/ttm/ttm_bo_api.h>
4struct ttm_dma_tt;
5
6#include <nvif/mem.h>
7#include <nvif/vmm.h>
8
9static inline struct nouveau_mem *
10nouveau_mem(struct ttm_mem_reg *reg)
11{
12 return reg->mm_node;
13}
14
15struct nouveau_mem {
16 struct nouveau_cli *cli;
17 u8 kind;
18 u8 comp;
19 struct nvif_mem mem;
20 struct nvif_vma vma[2];
21};
22
23int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp,
24 struct ttm_mem_reg *);
25void nouveau_mem_del(struct ttm_mem_reg *);
26int nouveau_mem_vram(struct ttm_mem_reg *, bool contig, u8 page);
27int nouveau_mem_host(struct ttm_mem_reg *, struct ttm_dma_tt *);
28void nouveau_mem_fini(struct nouveau_mem *);
29int nouveau_mem_map(struct nouveau_mem *, struct nvif_vmm *, struct nvif_vma *);
30#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index b7ab268f7d6f..941bf33bd249 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -2,6 +2,7 @@
2#include <linux/slab.h> 2#include <linux/slab.h>
3 3
4#include "nouveau_drv.h" 4#include "nouveau_drv.h"
5#include "nouveau_mem.h"
5#include "nouveau_ttm.h" 6#include "nouveau_ttm.h"
6 7
7struct nouveau_sgdma_be { 8struct nouveau_sgdma_be {
@@ -9,7 +10,7 @@ struct nouveau_sgdma_be {
9 * nouve_bo.c works properly, otherwise have to move them here 10 * nouve_bo.c works properly, otherwise have to move them here
10 */ 11 */
11 struct ttm_dma_tt ttm; 12 struct ttm_dma_tt ttm;
12 struct nvkm_mem *node; 13 struct nouveau_mem *mem;
13}; 14};
14 15
15static void 16static void
@@ -27,19 +28,20 @@ static int
27nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) 28nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
28{ 29{
29 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 30 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
30 struct nvkm_mem *node = reg->mm_node; 31 struct nouveau_mem *mem = nouveau_mem(reg);
31 32 int ret;
32 if (ttm->sg) { 33
33 node->sg = ttm->sg; 34 ret = nouveau_mem_host(reg, &nvbe->ttm);
34 node->pages = NULL; 35 if (ret)
35 } else { 36 return ret;
36 node->sg = NULL; 37
37 node->pages = nvbe->ttm.dma_address; 38 ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]);
39 if (ret) {
40 nouveau_mem_fini(mem);
41 return ret;
38 } 42 }
39 node->size = (reg->num_pages << PAGE_SHIFT) >> 12;
40 43
41 nvkm_vm_map(&node->vma[0], node); 44 nvbe->mem = mem;
42 nvbe->node = node;
43 return 0; 45 return 0;
44} 46}
45 47
@@ -47,7 +49,7 @@ static int
47nv04_sgdma_unbind(struct ttm_tt *ttm) 49nv04_sgdma_unbind(struct ttm_tt *ttm)
48{ 50{
49 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 51 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
50 nvkm_vm_unmap(&nvbe->node->vma[0]); 52 nouveau_mem_fini(nvbe->mem);
51 return 0; 53 return 0;
52} 54}
53 55
@@ -61,30 +63,20 @@ static int
61nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) 63nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
62{ 64{
63 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; 65 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
64 struct nvkm_mem *node = reg->mm_node; 66 struct nouveau_mem *mem = nouveau_mem(reg);
65 67 int ret;
66 /* noop: bound in move_notify() */
67 if (ttm->sg) {
68 node->sg = ttm->sg;
69 node->pages = NULL;
70 } else {
71 node->sg = NULL;
72 node->pages = nvbe->ttm.dma_address;
73 }
74 node->size = (reg->num_pages << PAGE_SHIFT) >> 12;
75 return 0;
76}
77 68
78static int 69 ret = nouveau_mem_host(reg, &nvbe->ttm);
79nv50_sgdma_unbind(struct ttm_tt *ttm) 70 if (ret)
80{ 71 return ret;
81 /* noop: unbound in move_notify() */ 72
73 nvbe->mem = mem;
82 return 0; 74 return 0;
83} 75}
84 76
85static struct ttm_backend_func nv50_sgdma_backend = { 77static struct ttm_backend_func nv50_sgdma_backend = {
86 .bind = nv50_sgdma_bind, 78 .bind = nv50_sgdma_bind,
87 .unbind = nv50_sgdma_unbind, 79 .unbind = nv04_sgdma_unbind,
88 .destroy = nouveau_sgdma_destroy 80 .destroy = nouveau_sgdma_destroy
89}; 81};
90 82
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index b0ad7fcefcf5..08b974b30482 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -23,53 +23,37 @@
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */ 25 */
26
27#include "nouveau_drv.h" 26#include "nouveau_drv.h"
28#include "nouveau_ttm.h"
29#include "nouveau_gem.h" 27#include "nouveau_gem.h"
28#include "nouveau_mem.h"
29#include "nouveau_ttm.h"
30 30
31#include <drm/drm_legacy.h> 31#include <drm/drm_legacy.h>
32 32
33#include <core/tegra.h> 33#include <core/tegra.h>
34 34
35static int 35static int
36nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) 36nouveau_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
37{ 37{
38 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
39 struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
40 man->priv = fb;
41 return 0; 38 return 0;
42} 39}
43 40
44static int 41static int
45nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) 42nouveau_manager_fini(struct ttm_mem_type_manager *man)
46{ 43{
47 man->priv = NULL;
48 return 0; 44 return 0;
49} 45}
50 46
51static inline void 47static void
52nvkm_mem_node_cleanup(struct nvkm_mem *node) 48nouveau_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg)
53{ 49{
54 if (node->vma[0].node) { 50 nouveau_mem_del(reg);
55 nvkm_vm_unmap(&node->vma[0]);
56 nvkm_vm_put(&node->vma[0]);
57 }
58
59 if (node->vma[1].node) {
60 nvkm_vm_unmap(&node->vma[1]);
61 nvkm_vm_put(&node->vma[1]);
62 }
63} 51}
64 52
65static void 53static void
66nouveau_vram_manager_del(struct ttm_mem_type_manager *man, 54nouveau_manager_debug(struct ttm_mem_type_manager *man,
67 struct ttm_mem_reg *reg) 55 struct drm_printer *printer)
68{ 56{
69 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
70 struct nvkm_ram *ram = nvxx_fb(&drm->client.device)->ram;
71 nvkm_mem_node_cleanup(reg->mm_node);
72 ram->func->put(ram, (struct nvkm_mem **)&reg->mm_node);
73} 57}
74 58
75static int 59static int
@@ -78,192 +62,105 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
78 const struct ttm_place *place, 62 const struct ttm_place *place,
79 struct ttm_mem_reg *reg) 63 struct ttm_mem_reg *reg)
80{ 64{
81 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
82 struct nvkm_ram *ram = nvxx_fb(&drm->client.device)->ram;
83 struct nouveau_bo *nvbo = nouveau_bo(bo); 65 struct nouveau_bo *nvbo = nouveau_bo(bo);
84 struct nvkm_mem *node; 66 struct nouveau_drm *drm = nvbo->cli->drm;
85 u32 size_nc = 0; 67 struct nouveau_mem *mem;
86 int ret; 68 int ret;
87 69
88 if (drm->client.device.info.ram_size == 0) 70 if (drm->client.device.info.ram_size == 0)
89 return -ENOMEM; 71 return -ENOMEM;
90 72
91 if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) 73 ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg);
92 size_nc = 1 << nvbo->page_shift; 74 mem = nouveau_mem(reg);
75 if (ret)
76 return ret;
93 77
94 ret = ram->func->get(ram, reg->num_pages << PAGE_SHIFT, 78 ret = nouveau_mem_vram(reg, nvbo->contig, nvbo->page);
95 reg->page_alignment << PAGE_SHIFT, size_nc,
96 (nvbo->tile_flags >> 8) & 0x3ff, &node);
97 if (ret) { 79 if (ret) {
98 reg->mm_node = NULL; 80 nouveau_mem_del(reg);
99 return (ret == -ENOSPC) ? 0 : ret; 81 if (ret == -ENOSPC) {
82 reg->mm_node = NULL;
83 return 0;
84 }
85 return ret;
100 } 86 }
101 87
102 node->page_shift = nvbo->page_shift;
103
104 reg->mm_node = node;
105 reg->start = node->offset >> PAGE_SHIFT;
106 return 0; 88 return 0;
107} 89}
108 90
109const struct ttm_mem_type_manager_func nouveau_vram_manager = { 91const struct ttm_mem_type_manager_func nouveau_vram_manager = {
110 .init = nouveau_vram_manager_init, 92 .init = nouveau_manager_init,
111 .takedown = nouveau_vram_manager_fini, 93 .takedown = nouveau_manager_fini,
112 .get_node = nouveau_vram_manager_new, 94 .get_node = nouveau_vram_manager_new,
113 .put_node = nouveau_vram_manager_del, 95 .put_node = nouveau_manager_del,
96 .debug = nouveau_manager_debug,
114}; 97};
115 98
116static int 99static int
117nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
118{
119 return 0;
120}
121
122static int
123nouveau_gart_manager_fini(struct ttm_mem_type_manager *man)
124{
125 return 0;
126}
127
128static void
129nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
130 struct ttm_mem_reg *reg)
131{
132 nvkm_mem_node_cleanup(reg->mm_node);
133 kfree(reg->mm_node);
134 reg->mm_node = NULL;
135}
136
137static int
138nouveau_gart_manager_new(struct ttm_mem_type_manager *man, 100nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
139 struct ttm_buffer_object *bo, 101 struct ttm_buffer_object *bo,
140 const struct ttm_place *place, 102 const struct ttm_place *place,
141 struct ttm_mem_reg *reg) 103 struct ttm_mem_reg *reg)
142{ 104{
143 struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
144 struct nouveau_bo *nvbo = nouveau_bo(bo); 105 struct nouveau_bo *nvbo = nouveau_bo(bo);
145 struct nvkm_mem *node; 106 struct nouveau_drm *drm = nvbo->cli->drm;
146 107 struct nouveau_mem *mem;
147 node = kzalloc(sizeof(*node), GFP_KERNEL); 108 int ret;
148 if (!node)
149 return -ENOMEM;
150 109
151 node->page_shift = 12; 110 ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg);
152 111 mem = nouveau_mem(reg);
153 switch (drm->client.device.info.family) { 112 if (ret)
154 case NV_DEVICE_INFO_V0_TNT: 113 return ret;
155 case NV_DEVICE_INFO_V0_CELSIUS:
156 case NV_DEVICE_INFO_V0_KELVIN:
157 case NV_DEVICE_INFO_V0_RANKINE:
158 case NV_DEVICE_INFO_V0_CURIE:
159 break;
160 case NV_DEVICE_INFO_V0_TESLA:
161 if (drm->client.device.info.chipset != 0x50)
162 node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
163 break;
164 case NV_DEVICE_INFO_V0_FERMI:
165 case NV_DEVICE_INFO_V0_KEPLER:
166 case NV_DEVICE_INFO_V0_MAXWELL:
167 case NV_DEVICE_INFO_V0_PASCAL:
168 node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
169 break;
170 default:
171 NV_WARN(drm, "%s: unhandled family type %x\n", __func__,
172 drm->client.device.info.family);
173 break;
174 }
175 114
176 reg->mm_node = node; 115 reg->start = 0;
177 reg->start = 0;
178 return 0; 116 return 0;
179} 117}
180 118
181static void
182nouveau_gart_manager_debug(struct ttm_mem_type_manager *man,
183 struct drm_printer *printer)
184{
185}
186
187const struct ttm_mem_type_manager_func nouveau_gart_manager = { 119const struct ttm_mem_type_manager_func nouveau_gart_manager = {
188 .init = nouveau_gart_manager_init, 120 .init = nouveau_manager_init,
189 .takedown = nouveau_gart_manager_fini, 121 .takedown = nouveau_manager_fini,
190 .get_node = nouveau_gart_manager_new, 122 .get_node = nouveau_gart_manager_new,
191 .put_node = nouveau_gart_manager_del, 123 .put_node = nouveau_manager_del,
192 .debug = nouveau_gart_manager_debug 124 .debug = nouveau_manager_debug
193}; 125};
194 126
195/*XXX*/
196#include <subdev/mmu/nv04.h>
197static int
198nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
199{
200 struct nouveau_drm *drm = nouveau_bdev(man->bdev);
201 struct nvkm_mmu *mmu = nvxx_mmu(&drm->client.device);
202 struct nv04_mmu *priv = (void *)mmu;
203 struct nvkm_vm *vm = NULL;
204 nvkm_vm_ref(priv->vm, &vm, NULL);
205 man->priv = vm;
206 return 0;
207}
208
209static int
210nv04_gart_manager_fini(struct ttm_mem_type_manager *man)
211{
212 struct nvkm_vm *vm = man->priv;
213 nvkm_vm_ref(NULL, &vm, NULL);
214 man->priv = NULL;
215 return 0;
216}
217
218static void
219nv04_gart_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg)
220{
221 struct nvkm_mem *node = reg->mm_node;
222 if (node->vma[0].node)
223 nvkm_vm_put(&node->vma[0]);
224 kfree(reg->mm_node);
225 reg->mm_node = NULL;
226}
227
228static int 127static int
229nv04_gart_manager_new(struct ttm_mem_type_manager *man, 128nv04_gart_manager_new(struct ttm_mem_type_manager *man,
230 struct ttm_buffer_object *bo, 129 struct ttm_buffer_object *bo,
231 const struct ttm_place *place, 130 const struct ttm_place *place,
232 struct ttm_mem_reg *reg) 131 struct ttm_mem_reg *reg)
233{ 132{
234 struct nvkm_mem *node; 133 struct nouveau_bo *nvbo = nouveau_bo(bo);
134 struct nouveau_drm *drm = nvbo->cli->drm;
135 struct nouveau_mem *mem;
235 int ret; 136 int ret;
236 137
237 node = kzalloc(sizeof(*node), GFP_KERNEL); 138 ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg);
238 if (!node) 139 mem = nouveau_mem(reg);
239 return -ENOMEM; 140 if (ret)
240 141 return ret;
241 node->page_shift = 12;
242 142
243 ret = nvkm_vm_get(man->priv, reg->num_pages << 12, node->page_shift, 143 ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0,
244 NV_MEM_ACCESS_RW, &node->vma[0]); 144 reg->num_pages << PAGE_SHIFT, &mem->vma[0]);
245 if (ret) { 145 if (ret) {
246 kfree(node); 146 nouveau_mem_del(reg);
147 if (ret == -ENOSPC) {
148 reg->mm_node = NULL;
149 return 0;
150 }
247 return ret; 151 return ret;
248 } 152 }
249 153
250 reg->mm_node = node; 154 reg->start = mem->vma[0].addr >> PAGE_SHIFT;
251 reg->start = node->vma[0].offset >> PAGE_SHIFT;
252 return 0; 155 return 0;
253} 156}
254 157
255static void
256nv04_gart_manager_debug(struct ttm_mem_type_manager *man,
257 struct drm_printer *printer)
258{
259}
260
261const struct ttm_mem_type_manager_func nv04_gart_manager = { 158const struct ttm_mem_type_manager_func nv04_gart_manager = {
262 .init = nv04_gart_manager_init, 159 .init = nouveau_manager_init,
263 .takedown = nv04_gart_manager_fini, 160 .takedown = nouveau_manager_fini,
264 .get_node = nv04_gart_manager_new, 161 .get_node = nv04_gart_manager_new,
265 .put_node = nv04_gart_manager_del, 162 .put_node = nouveau_manager_del,
266 .debug = nv04_gart_manager_debug 163 .debug = nouveau_manager_debug
267}; 164};
268 165
269int 166int
@@ -343,44 +240,43 @@ nouveau_ttm_init(struct nouveau_drm *drm)
343{ 240{
344 struct nvkm_device *device = nvxx_device(&drm->client.device); 241 struct nvkm_device *device = nvxx_device(&drm->client.device);
345 struct nvkm_pci *pci = device->pci; 242 struct nvkm_pci *pci = device->pci;
243 struct nvif_mmu *mmu = &drm->client.mmu;
346 struct drm_device *dev = drm->dev; 244 struct drm_device *dev = drm->dev;
347 u8 bits; 245 int typei, ret;
348 int ret;
349 246
350 if (pci && pci->agp.bridge) { 247 typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE |
351 drm->agp.bridge = pci->agp.bridge; 248 NVIF_MEM_COHERENT);
352 drm->agp.base = pci->agp.base; 249 if (typei < 0)
353 drm->agp.size = pci->agp.size; 250 return -ENOSYS;
354 drm->agp.cma = pci->agp.cma;
355 }
356 251
357 bits = nvxx_mmu(&drm->client.device)->dma_bits; 252 drm->ttm.type_host = typei;
358 if (nvxx_device(&drm->client.device)->func->pci) {
359 if (drm->agp.bridge)
360 bits = 32;
361 } else if (device->func->tegra) {
362 struct nvkm_device_tegra *tegra = device->func->tegra(device);
363 253
364 /* 254 typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE);
365 * If the platform can use a IOMMU, then the addressable DMA 255 if (typei < 0)
366 * space is constrained by the IOMMU bit 256 return -ENOSYS;
367 */
368 if (tegra->func->iommu_bit)
369 bits = min(bits, tegra->func->iommu_bit);
370 257
371 } 258 drm->ttm.type_ncoh = typei;
372 259
373 ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); 260 if (drm->client.device.info.platform != NV_DEVICE_INFO_V0_SOC &&
374 if (ret && bits != 32) { 261 drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
375 bits = 32; 262 typei = nvif_mmu_type(mmu, NVIF_MEM_VRAM | NVIF_MEM_MAPPABLE |
376 ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); 263 NVIF_MEM_KIND |
264 NVIF_MEM_COMP |
265 NVIF_MEM_DISP);
266 if (typei < 0)
267 return -ENOSYS;
268
269 drm->ttm.type_vram = typei;
270 } else {
271 drm->ttm.type_vram = -1;
377 } 272 }
378 if (ret)
379 return ret;
380 273
381 ret = dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(bits)); 274 if (pci && pci->agp.bridge) {
382 if (ret) 275 drm->agp.bridge = pci->agp.bridge;
383 dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(32)); 276 drm->agp.base = pci->agp.base;
277 drm->agp.size = pci->agp.size;
278 drm->agp.cma = pci->agp.cma;
279 }
384 280
385 ret = nouveau_ttm_global_init(drm); 281 ret = nouveau_ttm_global_init(drm);
386 if (ret) 282 if (ret)
@@ -391,7 +287,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
391 &nouveau_bo_driver, 287 &nouveau_bo_driver,
392 dev->anon_inode->i_mapping, 288 dev->anon_inode->i_mapping,
393 DRM_FILE_PAGE_OFFSET, 289 DRM_FILE_PAGE_OFFSET,
394 bits <= 32 ? true : false); 290 drm->client.mmu.dmabits <= 32 ? true : false);
395 if (ret) { 291 if (ret) {
396 NV_ERROR(drm, "error initialising bo driver, %d\n", ret); 292 NV_ERROR(drm, "error initialising bo driver, %d\n", ret);
397 return ret; 293 return ret;
@@ -415,7 +311,7 @@ nouveau_ttm_init(struct nouveau_drm *drm)
415 311
416 /* GART init */ 312 /* GART init */
417 if (!drm->agp.bridge) { 313 if (!drm->agp.bridge) {
418 drm->gem.gart_available = nvxx_mmu(&drm->client.device)->limit; 314 drm->gem.gart_available = drm->client.vmm.vmm.limit;
419 } else { 315 } else {
420 drm->gem.gart_available = drm->agp.size; 316 drm->gem.gart_available = drm->agp.size;
421 } 317 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c
new file mode 100644
index 000000000000..9e2628dd8e4d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c
@@ -0,0 +1,135 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "nouveau_vmm.h"
23#include "nouveau_drv.h"
24#include "nouveau_bo.h"
25#include "nouveau_mem.h"
26
27void
28nouveau_vma_unmap(struct nouveau_vma *vma)
29{
30 if (vma->mem) {
31 nvif_vmm_unmap(&vma->vmm->vmm, vma->addr);
32 vma->mem = NULL;
33 }
34}
35
36int
37nouveau_vma_map(struct nouveau_vma *vma, struct nouveau_mem *mem)
38{
39 struct nvif_vma tmp = { .addr = vma->addr };
40 int ret = nouveau_mem_map(mem, &vma->vmm->vmm, &tmp);
41 if (ret)
42 return ret;
43 vma->mem = mem;
44 return 0;
45}
46
47struct nouveau_vma *
48nouveau_vma_find(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm)
49{
50 struct nouveau_vma *vma;
51
52 list_for_each_entry(vma, &nvbo->vma_list, head) {
53 if (vma->vmm == vmm)
54 return vma;
55 }
56
57 return NULL;
58}
59
60void
61nouveau_vma_del(struct nouveau_vma **pvma)
62{
63 struct nouveau_vma *vma = *pvma;
64 if (vma && --vma->refs <= 0) {
65 if (likely(vma->addr != ~0ULL)) {
66 struct nvif_vma tmp = { .addr = vma->addr, .size = 1 };
67 nvif_vmm_put(&vma->vmm->vmm, &tmp);
68 }
69 list_del(&vma->head);
70 *pvma = NULL;
71 kfree(*pvma);
72 }
73}
74
75int
76nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm,
77 struct nouveau_vma **pvma)
78{
79 struct nouveau_mem *mem = nouveau_mem(&nvbo->bo.mem);
80 struct nouveau_vma *vma;
81 struct nvif_vma tmp;
82 int ret;
83
84 if ((vma = *pvma = nouveau_vma_find(nvbo, vmm))) {
85 vma->refs++;
86 return 0;
87 }
88
89 if (!(vma = *pvma = kmalloc(sizeof(*vma), GFP_KERNEL)))
90 return -ENOMEM;
91 vma->vmm = vmm;
92 vma->refs = 1;
93 vma->addr = ~0ULL;
94 vma->mem = NULL;
95 list_add_tail(&vma->head, &nvbo->vma_list);
96
97 if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM &&
98 mem->mem.page == nvbo->page) {
99 ret = nvif_vmm_get(&vmm->vmm, LAZY, false, mem->mem.page, 0,
100 mem->mem.size, &tmp);
101 if (ret)
102 goto done;
103
104 vma->addr = tmp.addr;
105 ret = nouveau_vma_map(vma, mem);
106 } else {
107 ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0,
108 mem->mem.size, &tmp);
109 vma->addr = tmp.addr;
110 }
111
112done:
113 if (ret)
114 nouveau_vma_del(pvma);
115 return ret;
116}
117
118void
119nouveau_vmm_fini(struct nouveau_vmm *vmm)
120{
121 nvif_vmm_fini(&vmm->vmm);
122 vmm->cli = NULL;
123}
124
125int
126nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm)
127{
128 int ret = nvif_vmm_init(&cli->mmu, oclass, PAGE_SIZE, 0, NULL, 0,
129 &vmm->vmm);
130 if (ret)
131 return ret;
132
133 vmm->cli = cli;
134 return 0;
135}
diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.h b/drivers/gpu/drm/nouveau/nouveau_vmm.h
new file mode 100644
index 000000000000..5c31f43678d3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_vmm.h
@@ -0,0 +1,31 @@
1#ifndef __NOUVEAU_VMA_H__
2#define __NOUVEAU_VMA_H__
3#include <nvif/vmm.h>
4struct nouveau_bo;
5struct nouveau_mem;
6
7struct nouveau_vma {
8 struct nouveau_vmm *vmm;
9 int refs;
10 struct list_head head;
11 u64 addr;
12
13 struct nouveau_mem *mem;
14};
15
16struct nouveau_vma *nouveau_vma_find(struct nouveau_bo *, struct nouveau_vmm *);
17int nouveau_vma_new(struct nouveau_bo *, struct nouveau_vmm *,
18 struct nouveau_vma **);
19void nouveau_vma_del(struct nouveau_vma **);
20int nouveau_vma_map(struct nouveau_vma *, struct nouveau_mem *);
21void nouveau_vma_unmap(struct nouveau_vma *);
22
23struct nouveau_vmm {
24 struct nouveau_cli *cli;
25 struct nvif_vmm vmm;
26 struct nvkm_vm *vm;
27};
28
29int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *);
30void nouveau_vmm_fini(struct nouveau_vmm *);
31#endif
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index e4751f92b342..92d46222c79d 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -318,7 +318,7 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
318 ret = nvif_object_init(disp, 0, oclass[0], 318 ret = nvif_object_init(disp, 0, oclass[0],
319 data, size, &chan->user); 319 data, size, &chan->user);
320 if (ret == 0) 320 if (ret == 0)
321 nvif_object_map(&chan->user); 321 nvif_object_map(&chan->user, NULL, 0);
322 nvif_object_sclass_put(&sclass); 322 nvif_object_sclass_put(&sclass);
323 return ret; 323 return ret;
324 } 324 }
@@ -424,7 +424,7 @@ nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb)
424{ 424{
425 struct nouveau_drm *drm = nouveau_drm(fb->base.dev); 425 struct nouveau_drm *drm = nouveau_drm(fb->base.dev);
426 struct nv50_dmac_ctxdma *ctxdma; 426 struct nv50_dmac_ctxdma *ctxdma;
427 const u8 kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; 427 const u8 kind = fb->nvbo->kind;
428 const u32 handle = 0xfb000000 | kind; 428 const u32 handle = 0xfb000000 | kind;
429 struct { 429 struct {
430 struct nv_dma_v0 base; 430 struct nv_dma_v0 base;
@@ -510,6 +510,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
510 int ret; 510 int ret;
511 511
512 mutex_init(&dmac->lock); 512 mutex_init(&dmac->lock);
513 INIT_LIST_HEAD(&dmac->ctxdma);
513 514
514 dmac->ptr = dma_alloc_coherent(nvxx_device(device)->dev, PAGE_SIZE, 515 dmac->ptr = dma_alloc_coherent(nvxx_device(device)->dev, PAGE_SIZE,
515 &dmac->handle, GFP_KERNEL); 516 &dmac->handle, GFP_KERNEL);
@@ -556,7 +557,6 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
556 if (ret) 557 if (ret)
557 return ret; 558 return ret;
558 559
559 INIT_LIST_HEAD(&dmac->ctxdma);
560 return ret; 560 return ret;
561} 561}
562 562
@@ -847,7 +847,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
847 847
848 asyw->image.w = fb->base.width; 848 asyw->image.w = fb->base.width;
849 asyw->image.h = fb->base.height; 849 asyw->image.h = fb->base.height;
850 asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; 850 asyw->image.kind = fb->nvbo->kind;
851 851
852 if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) 852 if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
853 asyw->interval = 0; 853 asyw->interval = 0;
@@ -857,9 +857,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
857 if (asyw->image.kind) { 857 if (asyw->image.kind) {
858 asyw->image.layout = 0; 858 asyw->image.layout = 0;
859 if (drm->client.device.info.chipset >= 0xc0) 859 if (drm->client.device.info.chipset >= 0xc0)
860 asyw->image.block = fb->nvbo->tile_mode >> 4; 860 asyw->image.block = fb->nvbo->mode >> 4;
861 else 861 else
862 asyw->image.block = fb->nvbo->tile_mode; 862 asyw->image.block = fb->nvbo->mode;
863 asyw->image.pitch = (fb->base.pitches[0] / 4) << 4; 863 asyw->image.pitch = (fb->base.pitches[0] / 4) << 4;
864 } else { 864 } else {
865 asyw->image.layout = 1; 865 asyw->image.layout = 1;
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 327dcd7901ed..facd18564e0d 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -25,6 +25,7 @@
25#include "nouveau_drv.h" 25#include "nouveau_drv.h"
26#include "nouveau_dma.h" 26#include "nouveau_dma.h"
27#include "nouveau_fbcon.h" 27#include "nouveau_fbcon.h"
28#include "nouveau_vmm.h"
28 29
29int 30int
30nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 31nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -239,8 +240,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
239 OUT_RING(chan, info->fix.line_length); 240 OUT_RING(chan, info->fix.line_length);
240 OUT_RING(chan, info->var.xres_virtual); 241 OUT_RING(chan, info->var.xres_virtual);
241 OUT_RING(chan, info->var.yres_virtual); 242 OUT_RING(chan, info->var.yres_virtual);
242 OUT_RING(chan, upper_32_bits(fb->vma.offset)); 243 OUT_RING(chan, upper_32_bits(fb->vma->addr));
243 OUT_RING(chan, lower_32_bits(fb->vma.offset)); 244 OUT_RING(chan, lower_32_bits(fb->vma->addr));
244 BEGIN_NV04(chan, NvSub2D, 0x0230, 2); 245 BEGIN_NV04(chan, NvSub2D, 0x0230, 2);
245 OUT_RING(chan, format); 246 OUT_RING(chan, format);
246 OUT_RING(chan, 1); 247 OUT_RING(chan, 1);
@@ -248,8 +249,8 @@ nv50_fbcon_accel_init(struct fb_info *info)
248 OUT_RING(chan, info->fix.line_length); 249 OUT_RING(chan, info->fix.line_length);
249 OUT_RING(chan, info->var.xres_virtual); 250 OUT_RING(chan, info->var.xres_virtual);
250 OUT_RING(chan, info->var.yres_virtual); 251 OUT_RING(chan, info->var.yres_virtual);
251 OUT_RING(chan, upper_32_bits(fb->vma.offset)); 252 OUT_RING(chan, upper_32_bits(fb->vma->addr));
252 OUT_RING(chan, lower_32_bits(fb->vma.offset)); 253 OUT_RING(chan, lower_32_bits(fb->vma->addr));
253 FIRE_RING(chan); 254 FIRE_RING(chan);
254 255
255 return 0; 256 return 0;
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index bd7a8a1e4ad9..5f0c0c27d5dc 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -25,6 +25,7 @@
25#include "nouveau_drv.h" 25#include "nouveau_drv.h"
26#include "nouveau_dma.h" 26#include "nouveau_dma.h"
27#include "nouveau_fence.h" 27#include "nouveau_fence.h"
28#include "nouveau_vmm.h"
28 29
29#include "nv50_display.h" 30#include "nv50_display.h"
30 31
@@ -68,12 +69,7 @@ nv84_fence_emit(struct nouveau_fence *fence)
68{ 69{
69 struct nouveau_channel *chan = fence->channel; 70 struct nouveau_channel *chan = fence->channel;
70 struct nv84_fence_chan *fctx = chan->fence; 71 struct nv84_fence_chan *fctx = chan->fence;
71 u64 addr = chan->chid * 16; 72 u64 addr = fctx->vma->addr + chan->chid * 16;
72
73 if (fence->sysmem)
74 addr += fctx->vma_gart.offset;
75 else
76 addr += fctx->vma.offset;
77 73
78 return fctx->base.emit32(chan, addr, fence->base.seqno); 74 return fctx->base.emit32(chan, addr, fence->base.seqno);
79} 75}
@@ -83,12 +79,7 @@ nv84_fence_sync(struct nouveau_fence *fence,
83 struct nouveau_channel *prev, struct nouveau_channel *chan) 79 struct nouveau_channel *prev, struct nouveau_channel *chan)
84{ 80{
85 struct nv84_fence_chan *fctx = chan->fence; 81 struct nv84_fence_chan *fctx = chan->fence;
86 u64 addr = prev->chid * 16; 82 u64 addr = fctx->vma->addr + prev->chid * 16;
87
88 if (fence->sysmem)
89 addr += fctx->vma_gart.offset;
90 else
91 addr += fctx->vma.offset;
92 83
93 return fctx->base.sync32(chan, addr, fence->base.seqno); 84 return fctx->base.sync32(chan, addr, fence->base.seqno);
94} 85}
@@ -108,8 +99,7 @@ nv84_fence_context_del(struct nouveau_channel *chan)
108 99
109 nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); 100 nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
110 mutex_lock(&priv->mutex); 101 mutex_lock(&priv->mutex);
111 nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); 102 nouveau_vma_del(&fctx->vma);
112 nouveau_bo_vma_del(priv->bo, &fctx->vma);
113 mutex_unlock(&priv->mutex); 103 mutex_unlock(&priv->mutex);
114 nouveau_fence_context_del(&fctx->base); 104 nouveau_fence_context_del(&fctx->base);
115 chan->fence = NULL; 105 chan->fence = NULL;
@@ -137,11 +127,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
137 fctx->base.sequence = nv84_fence_read(chan); 127 fctx->base.sequence = nv84_fence_read(chan);
138 128
139 mutex_lock(&priv->mutex); 129 mutex_lock(&priv->mutex);
140 ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma); 130 ret = nouveau_vma_new(priv->bo, &cli->vmm, &fctx->vma);
141 if (ret == 0) {
142 ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
143 &fctx->vma_gart);
144 }
145 mutex_unlock(&priv->mutex); 131 mutex_unlock(&priv->mutex);
146 132
147 if (ret) 133 if (ret)
@@ -182,10 +168,6 @@ static void
182nv84_fence_destroy(struct nouveau_drm *drm) 168nv84_fence_destroy(struct nouveau_drm *drm)
183{ 169{
184 struct nv84_fence_priv *priv = drm->fence; 170 struct nv84_fence_priv *priv = drm->fence;
185 nouveau_bo_unmap(priv->bo_gart);
186 if (priv->bo_gart)
187 nouveau_bo_unpin(priv->bo_gart);
188 nouveau_bo_ref(NULL, &priv->bo_gart);
189 nouveau_bo_unmap(priv->bo); 171 nouveau_bo_unmap(priv->bo);
190 if (priv->bo) 172 if (priv->bo)
191 nouveau_bo_unpin(priv->bo); 173 nouveau_bo_unpin(priv->bo);
@@ -238,21 +220,6 @@ nv84_fence_create(struct nouveau_drm *drm)
238 nouveau_bo_ref(NULL, &priv->bo); 220 nouveau_bo_ref(NULL, &priv->bo);
239 } 221 }
240 222
241 if (ret == 0)
242 ret = nouveau_bo_new(&drm->client, 16 * priv->base.contexts, 0,
243 TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED, 0,
244 0, NULL, NULL, &priv->bo_gart);
245 if (ret == 0) {
246 ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT, false);
247 if (ret == 0) {
248 ret = nouveau_bo_map(priv->bo_gart);
249 if (ret)
250 nouveau_bo_unpin(priv->bo_gart);
251 }
252 if (ret)
253 nouveau_bo_ref(NULL, &priv->bo_gart);
254 }
255
256 if (ret) 223 if (ret)
257 nv84_fence_destroy(drm); 224 nv84_fence_destroy(drm);
258 return ret; 225 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index 90f27bfa381f..c0deef4fe727 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -25,6 +25,7 @@
25#include "nouveau_drv.h" 25#include "nouveau_drv.h"
26#include "nouveau_dma.h" 26#include "nouveau_dma.h"
27#include "nouveau_fbcon.h" 27#include "nouveau_fbcon.h"
28#include "nouveau_vmm.h"
28 29
29int 30int
30nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 31nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -239,8 +240,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
239 OUT_RING (chan, info->fix.line_length); 240 OUT_RING (chan, info->fix.line_length);
240 OUT_RING (chan, info->var.xres_virtual); 241 OUT_RING (chan, info->var.xres_virtual);
241 OUT_RING (chan, info->var.yres_virtual); 242 OUT_RING (chan, info->var.yres_virtual);
242 OUT_RING (chan, upper_32_bits(fb->vma.offset)); 243 OUT_RING (chan, upper_32_bits(fb->vma->addr));
243 OUT_RING (chan, lower_32_bits(fb->vma.offset)); 244 OUT_RING (chan, lower_32_bits(fb->vma->addr));
244 BEGIN_NVC0(chan, NvSub2D, 0x0230, 10); 245 BEGIN_NVC0(chan, NvSub2D, 0x0230, 10);
245 OUT_RING (chan, format); 246 OUT_RING (chan, format);
246 OUT_RING (chan, 1); 247 OUT_RING (chan, 1);
@@ -250,8 +251,8 @@ nvc0_fbcon_accel_init(struct fb_info *info)
250 OUT_RING (chan, info->fix.line_length); 251 OUT_RING (chan, info->fix.line_length);
251 OUT_RING (chan, info->var.xres_virtual); 252 OUT_RING (chan, info->var.xres_virtual);
252 OUT_RING (chan, info->var.yres_virtual); 253 OUT_RING (chan, info->var.yres_virtual);
253 OUT_RING (chan, upper_32_bits(fb->vma.offset)); 254 OUT_RING (chan, upper_32_bits(fb->vma->addr));
254 OUT_RING (chan, lower_32_bits(fb->vma.offset)); 255 OUT_RING (chan, lower_32_bits(fb->vma->addr));
255 FIRE_RING (chan); 256 FIRE_RING (chan);
256 257
257 return 0; 258 return 0;
diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild
index 067b5e9f5ec1..f1675a4ab6fa 100644
--- a/drivers/gpu/drm/nouveau/nvif/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvif/Kbuild
@@ -2,4 +2,7 @@ nvif-y := nvif/object.o
2nvif-y += nvif/client.o 2nvif-y += nvif/client.o
3nvif-y += nvif/device.o 3nvif-y += nvif/device.o
4nvif-y += nvif/driver.o 4nvif-y += nvif/driver.o
5nvif-y += nvif/mem.o
6nvif-y += nvif/mmu.o
5nvif-y += nvif/notify.o 7nvif-y += nvif/notify.o
8nvif-y += nvif/vmm.o
diff --git a/drivers/gpu/drm/nouveau/nvif/mem.c b/drivers/gpu/drm/nouveau/nvif/mem.c
new file mode 100644
index 000000000000..0f9382c60145
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/mem.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include <nvif/mem.h>
23#include <nvif/client.h>
24
25#include <nvif/if000a.h>
26
27void
28nvif_mem_fini(struct nvif_mem *mem)
29{
30 nvif_object_fini(&mem->object);
31}
32
33int
34nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page,
35 u64 size, void *argv, u32 argc, struct nvif_mem *mem)
36{
37 struct nvif_mem_v0 *args;
38 u8 stack[128];
39 int ret;
40
41 mem->object.client = NULL;
42 if (type < 0)
43 return -EINVAL;
44
45 if (sizeof(*args) + argc > sizeof(stack)) {
46 if (!(args = kmalloc(sizeof(*args) + argc, GFP_KERNEL)))
47 return -ENOMEM;
48 } else {
49 args = (void *)stack;
50 }
51 args->version = 0;
52 args->type = type;
53 args->page = page;
54 args->size = size;
55 memcpy(args->data, argv, argc);
56
57 ret = nvif_object_init(&mmu->object, 0, oclass, args,
58 sizeof(*args) + argc, &mem->object);
59 if (ret == 0) {
60 mem->type = mmu->type[type].type;
61 mem->page = args->page;
62 mem->addr = args->addr;
63 mem->size = args->size;
64 }
65
66 if (args != (void *)stack)
67 kfree(args);
68 return ret;
69
70}
71
72int
73nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page,
74 u64 size, void *argv, u32 argc, struct nvif_mem *mem)
75{
76 int ret = -EINVAL, i;
77
78 mem->object.client = NULL;
79
80 for (i = 0; ret && i < mmu->type_nr; i++) {
81 if ((mmu->type[i].type & type) == type) {
82 ret = nvif_mem_init_type(mmu, oclass, i, page, size,
83 argv, argc, mem);
84 }
85 }
86
87 return ret;
88}
diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c b/drivers/gpu/drm/nouveau/nvif/mmu.c
new file mode 100644
index 000000000000..15d0dcbf7ab4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/mmu.c
@@ -0,0 +1,117 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include <nvif/mmu.h>
23
24#include <nvif/class.h>
25#include <nvif/if0008.h>
26
27void
28nvif_mmu_fini(struct nvif_mmu *mmu)
29{
30 kfree(mmu->kind);
31 kfree(mmu->type);
32 kfree(mmu->heap);
33 nvif_object_fini(&mmu->object);
34}
35
36int
37nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
38{
39 struct nvif_mmu_v0 args;
40 int ret, i;
41
42 args.version = 0;
43 mmu->heap = NULL;
44 mmu->type = NULL;
45 mmu->kind = NULL;
46
47 ret = nvif_object_init(parent, 0, oclass, &args, sizeof(args),
48 &mmu->object);
49 if (ret)
50 goto done;
51
52 mmu->dmabits = args.dmabits;
53 mmu->heap_nr = args.heap_nr;
54 mmu->type_nr = args.type_nr;
55 mmu->kind_nr = args.kind_nr;
56
57 mmu->heap = kmalloc(sizeof(*mmu->heap) * mmu->heap_nr, GFP_KERNEL);
58 mmu->type = kmalloc(sizeof(*mmu->type) * mmu->type_nr, GFP_KERNEL);
59 if (ret = -ENOMEM, !mmu->heap || !mmu->type)
60 goto done;
61
62 mmu->kind = kmalloc(sizeof(*mmu->kind) * mmu->kind_nr, GFP_KERNEL);
63 if (!mmu->kind && mmu->kind_nr)
64 goto done;
65
66 for (i = 0; i < mmu->heap_nr; i++) {
67 struct nvif_mmu_heap_v0 args = { .index = i };
68
69 ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_HEAP,
70 &args, sizeof(args));
71 if (ret)
72 goto done;
73
74 mmu->heap[i].size = args.size;
75 }
76
77 for (i = 0; i < mmu->type_nr; i++) {
78 struct nvif_mmu_type_v0 args = { .index = i };
79
80 ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_TYPE,
81 &args, sizeof(args));
82 if (ret)
83 goto done;
84
85 mmu->type[i].type = 0;
86 if (args.vram) mmu->type[i].type |= NVIF_MEM_VRAM;
87 if (args.host) mmu->type[i].type |= NVIF_MEM_HOST;
88 if (args.comp) mmu->type[i].type |= NVIF_MEM_COMP;
89 if (args.disp) mmu->type[i].type |= NVIF_MEM_DISP;
90 if (args.kind ) mmu->type[i].type |= NVIF_MEM_KIND;
91 if (args.mappable) mmu->type[i].type |= NVIF_MEM_MAPPABLE;
92 if (args.coherent) mmu->type[i].type |= NVIF_MEM_COHERENT;
93 if (args.uncached) mmu->type[i].type |= NVIF_MEM_UNCACHED;
94 mmu->type[i].heap = args.heap;
95 }
96
97 if (mmu->kind_nr) {
98 struct nvif_mmu_kind_v0 *kind;
99 u32 argc = sizeof(*kind) + sizeof(*kind->data) * mmu->kind_nr;
100
101 if (ret = -ENOMEM, !(kind = kmalloc(argc, GFP_KERNEL)))
102 goto done;
103 kind->version = 0;
104 kind->count = mmu->kind_nr;
105
106 ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_KIND,
107 kind, argc);
108 if (ret == 0)
109 memcpy(mmu->kind, kind->data, kind->count);
110 kfree(kind);
111 }
112
113done:
114 if (ret)
115 nvif_mmu_fini(mmu);
116 return ret;
117}
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c
index c3fb6a20f567..40adfe9b334b 100644
--- a/drivers/gpu/drm/nouveau/nvif/object.c
+++ b/drivers/gpu/drm/nouveau/nvif/object.c
@@ -166,46 +166,77 @@ nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
166} 166}
167 167
168void 168void
169nvif_object_unmap(struct nvif_object *object) 169nvif_object_unmap_handle(struct nvif_object *object)
170{
171 struct {
172 struct nvif_ioctl_v0 ioctl;
173 struct nvif_ioctl_unmap unmap;
174 } args = {
175 .ioctl.type = NVIF_IOCTL_V0_UNMAP,
176 };
177
178 nvif_object_ioctl(object, &args, sizeof(args), NULL);
179}
180
181int
182nvif_object_map_handle(struct nvif_object *object, void *argv, u32 argc,
183 u64 *handle, u64 *length)
170{ 184{
171 if (object->map.size) { 185 struct {
172 struct nvif_client *client = object->client; 186 struct nvif_ioctl_v0 ioctl;
173 struct { 187 struct nvif_ioctl_map_v0 map;
174 struct nvif_ioctl_v0 ioctl; 188 } *args;
175 struct nvif_ioctl_unmap unmap; 189 u32 argn = sizeof(*args) + argc;
176 } args = { 190 int ret, maptype;
177 .ioctl.type = NVIF_IOCTL_V0_UNMAP, 191
178 }; 192 if (!(args = kzalloc(argn, GFP_KERNEL)))
193 return -ENOMEM;
194 args->ioctl.type = NVIF_IOCTL_V0_MAP;
195 memcpy(args->map.data, argv, argc);
179 196
180 if (object->map.ptr) { 197 ret = nvif_object_ioctl(object, args, argn, NULL);
198 *handle = args->map.handle;
199 *length = args->map.length;
200 maptype = args->map.type;
201 kfree(args);
202 return ret ? ret : (maptype == NVIF_IOCTL_MAP_V0_IO);
203}
204
205void
206nvif_object_unmap(struct nvif_object *object)
207{
208 struct nvif_client *client = object->client;
209 if (object->map.ptr) {
210 if (object->map.size) {
181 client->driver->unmap(client, object->map.ptr, 211 client->driver->unmap(client, object->map.ptr,
182 object->map.size); 212 object->map.size);
183 object->map.ptr = NULL; 213 object->map.size = 0;
184 } 214 }
185 215 object->map.ptr = NULL;
186 nvif_object_ioctl(object, &args, sizeof(args), NULL); 216 nvif_object_unmap_handle(object);
187 object->map.size = 0;
188 } 217 }
189} 218}
190 219
191int 220int
192nvif_object_map(struct nvif_object *object) 221nvif_object_map(struct nvif_object *object, void *argv, u32 argc)
193{ 222{
194 struct nvif_client *client = object->client; 223 struct nvif_client *client = object->client;
195 struct { 224 u64 handle, length;
196 struct nvif_ioctl_v0 ioctl; 225 int ret = nvif_object_map_handle(object, argv, argc, &handle, &length);
197 struct nvif_ioctl_map_v0 map; 226 if (ret >= 0) {
198 } args = { 227 if (ret) {
199 .ioctl.type = NVIF_IOCTL_V0_MAP, 228 object->map.ptr = client->driver->map(client,
200 }; 229 handle,
201 int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); 230 length);
202 if (ret == 0) { 231 if (ret = -ENOMEM, object->map.ptr) {
203 object->map.size = args.map.length; 232 object->map.size = length;
204 object->map.ptr = client->driver->map(client, args.map.handle, 233 return 0;
205 object->map.size); 234 }
206 if (ret = -ENOMEM, object->map.ptr) 235 } else {
236 object->map.ptr = (void *)(unsigned long)handle;
207 return 0; 237 return 0;
208 nvif_object_unmap(object); 238 }
239 nvif_object_unmap_handle(object);
209 } 240 }
210 return ret; 241 return ret;
211} 242}
diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c
new file mode 100644
index 000000000000..31cdb2d2e1ff
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/vmm.c
@@ -0,0 +1,167 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include <nvif/vmm.h>
23#include <nvif/mem.h>
24
25#include <nvif/if000c.h>
26
27int
28nvif_vmm_unmap(struct nvif_vmm *vmm, u64 addr)
29{
30 return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_UNMAP,
31 &(struct nvif_vmm_unmap_v0) { .addr = addr },
32 sizeof(struct nvif_vmm_unmap_v0));
33}
34
35int
36nvif_vmm_map(struct nvif_vmm *vmm, u64 addr, u64 size, void *argv, u32 argc,
37 struct nvif_mem *mem, u64 offset)
38{
39 struct nvif_vmm_map_v0 *args;
40 u8 stack[16];
41 int ret;
42
43 if (sizeof(*args) + argc > sizeof(stack)) {
44 if (!(args = kmalloc(sizeof(*args) + argc, GFP_KERNEL)))
45 return -ENOMEM;
46 } else {
47 args = (void *)stack;
48 }
49
50 args->version = 0;
51 args->addr = addr;
52 args->size = size;
53 args->memory = nvif_handle(&mem->object);
54 args->offset = offset;
55 memcpy(args->data, argv, argc);
56
57 ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_MAP,
58 args, sizeof(*args) + argc);
59 if (args != (void *)stack)
60 kfree(args);
61 return ret;
62}
63
64void
65nvif_vmm_put(struct nvif_vmm *vmm, struct nvif_vma *vma)
66{
67 if (vma->size) {
68 WARN_ON(nvif_object_mthd(&vmm->object, NVIF_VMM_V0_PUT,
69 &(struct nvif_vmm_put_v0) {
70 .addr = vma->addr,
71 }, sizeof(struct nvif_vmm_put_v0)));
72 vma->size = 0;
73 }
74}
75
76int
77nvif_vmm_get(struct nvif_vmm *vmm, enum nvif_vmm_get type, bool sparse,
78 u8 page, u8 align, u64 size, struct nvif_vma *vma)
79{
80 struct nvif_vmm_get_v0 args;
81 int ret;
82
83 args.version = vma->size = 0;
84 args.sparse = sparse;
85 args.page = page;
86 args.align = align;
87 args.size = size;
88
89 switch (type) {
90 case ADDR: args.type = NVIF_VMM_GET_V0_ADDR; break;
91 case PTES: args.type = NVIF_VMM_GET_V0_PTES; break;
92 case LAZY: args.type = NVIF_VMM_GET_V0_LAZY; break;
93 default:
94 WARN_ON(1);
95 return -EINVAL;
96 }
97
98 ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_GET,
99 &args, sizeof(args));
100 if (ret == 0) {
101 vma->addr = args.addr;
102 vma->size = args.size;
103 }
104 return ret;
105}
106
107void
108nvif_vmm_fini(struct nvif_vmm *vmm)
109{
110 kfree(vmm->page);
111 nvif_object_fini(&vmm->object);
112}
113
114int
115nvif_vmm_init(struct nvif_mmu *mmu, s32 oclass, u64 addr, u64 size,
116 void *argv, u32 argc, struct nvif_vmm *vmm)
117{
118 struct nvif_vmm_v0 *args;
119 u32 argn = sizeof(*args) + argc;
120 int ret = -ENOSYS, i;
121
122 vmm->object.client = NULL;
123 vmm->page = NULL;
124
125 if (!(args = kmalloc(argn, GFP_KERNEL)))
126 return -ENOMEM;
127 args->version = 0;
128 args->addr = addr;
129 args->size = size;
130 memcpy(args->data, argv, argc);
131
132 ret = nvif_object_init(&mmu->object, 0, oclass, args, argn,
133 &vmm->object);
134 if (ret)
135 goto done;
136
137 vmm->start = args->addr;
138 vmm->limit = args->size;
139
140 vmm->page_nr = args->page_nr;
141 vmm->page = kmalloc(sizeof(*vmm->page) * vmm->page_nr, GFP_KERNEL);
142 if (!vmm->page) {
143 ret = -ENOMEM;
144 goto done;
145 }
146
147 for (i = 0; i < vmm->page_nr; i++) {
148 struct nvif_vmm_page_v0 args = { .index = i };
149
150 ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_PAGE,
151 &args, sizeof(args));
152 if (ret)
153 break;
154
155 vmm->page[i].shift = args.shift;
156 vmm->page[i].sparse = args.sparse;
157 vmm->page[i].vram = args.vram;
158 vmm->page[i].host = args.host;
159 vmm->page[i].comp = args.comp;
160 }
161
162done:
163 if (ret)
164 nvif_vmm_fini(vmm);
165 kfree(args);
166 return ret;
167}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index 0d3a896892b4..ac671202919e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -301,5 +301,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
301 client->debug = nvkm_dbgopt(dbg, "CLIENT"); 301 client->debug = nvkm_dbgopt(dbg, "CLIENT");
302 client->objroot = RB_ROOT; 302 client->objroot = RB_ROOT;
303 client->ntfy = ntfy; 303 client->ntfy = ntfy;
304 INIT_LIST_HEAD(&client->umem);
305 spin_lock_init(&client->lock);
304 return 0; 306 return 0;
305} 307}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
index b6c916954a10..657231c3c098 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
@@ -126,6 +126,15 @@ nvkm_engine_init(struct nvkm_subdev *subdev)
126 return ret; 126 return ret;
127} 127}
128 128
129static int
130nvkm_engine_preinit(struct nvkm_subdev *subdev)
131{
132 struct nvkm_engine *engine = nvkm_engine(subdev);
133 if (engine->func->preinit)
134 engine->func->preinit(engine);
135 return 0;
136}
137
129static void * 138static void *
130nvkm_engine_dtor(struct nvkm_subdev *subdev) 139nvkm_engine_dtor(struct nvkm_subdev *subdev)
131{ 140{
@@ -138,6 +147,7 @@ nvkm_engine_dtor(struct nvkm_subdev *subdev)
138static const struct nvkm_subdev_func 147static const struct nvkm_subdev_func
139nvkm_engine_func = { 148nvkm_engine_func = {
140 .dtor = nvkm_engine_dtor, 149 .dtor = nvkm_engine_dtor,
150 .preinit = nvkm_engine_preinit,
141 .init = nvkm_engine_init, 151 .init = nvkm_engine_init,
142 .fini = nvkm_engine_fini, 152 .fini = nvkm_engine_fini,
143 .intr = nvkm_engine_intr, 153 .intr = nvkm_engine_intr,
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c b/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c
index a7bd22706b2a..d6de2b3ed2c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c
@@ -42,6 +42,14 @@ nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data)
42} 42}
43 43
44/* accessor functions for gpuobjs allocated directly from instmem */ 44/* accessor functions for gpuobjs allocated directly from instmem */
45static int
46nvkm_gpuobj_heap_map(struct nvkm_gpuobj *gpuobj, u64 offset,
47 struct nvkm_vmm *vmm, struct nvkm_vma *vma,
48 void *argv, u32 argc)
49{
50 return nvkm_memory_map(gpuobj->memory, offset, vmm, vma, argv, argc);
51}
52
45static u32 53static u32
46nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) 54nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset)
47{ 55{
@@ -67,6 +75,7 @@ nvkm_gpuobj_heap_fast = {
67 .release = nvkm_gpuobj_heap_release, 75 .release = nvkm_gpuobj_heap_release,
68 .rd32 = nvkm_gpuobj_rd32_fast, 76 .rd32 = nvkm_gpuobj_rd32_fast,
69 .wr32 = nvkm_gpuobj_wr32_fast, 77 .wr32 = nvkm_gpuobj_wr32_fast,
78 .map = nvkm_gpuobj_heap_map,
70}; 79};
71 80
72static const struct nvkm_gpuobj_func 81static const struct nvkm_gpuobj_func
@@ -74,6 +83,7 @@ nvkm_gpuobj_heap_slow = {
74 .release = nvkm_gpuobj_heap_release, 83 .release = nvkm_gpuobj_heap_release,
75 .rd32 = nvkm_gpuobj_heap_rd32, 84 .rd32 = nvkm_gpuobj_heap_rd32,
76 .wr32 = nvkm_gpuobj_heap_wr32, 85 .wr32 = nvkm_gpuobj_heap_wr32,
86 .map = nvkm_gpuobj_heap_map,
77}; 87};
78 88
79static void * 89static void *
@@ -90,9 +100,19 @@ nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj)
90static const struct nvkm_gpuobj_func 100static const struct nvkm_gpuobj_func
91nvkm_gpuobj_heap = { 101nvkm_gpuobj_heap = {
92 .acquire = nvkm_gpuobj_heap_acquire, 102 .acquire = nvkm_gpuobj_heap_acquire,
103 .map = nvkm_gpuobj_heap_map,
93}; 104};
94 105
95/* accessor functions for gpuobjs sub-allocated from a parent gpuobj */ 106/* accessor functions for gpuobjs sub-allocated from a parent gpuobj */
107static int
108nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, u64 offset,
109 struct nvkm_vmm *vmm, struct nvkm_vma *vma,
110 void *argv, u32 argc)
111{
112 return nvkm_memory_map(gpuobj->parent, gpuobj->node->offset + offset,
113 vmm, vma, argv, argc);
114}
115
96static u32 116static u32
97nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) 117nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset)
98{ 118{
@@ -118,6 +138,7 @@ nvkm_gpuobj_fast = {
118 .release = nvkm_gpuobj_release, 138 .release = nvkm_gpuobj_release,
119 .rd32 = nvkm_gpuobj_rd32_fast, 139 .rd32 = nvkm_gpuobj_rd32_fast,
120 .wr32 = nvkm_gpuobj_wr32_fast, 140 .wr32 = nvkm_gpuobj_wr32_fast,
141 .map = nvkm_gpuobj_map,
121}; 142};
122 143
123static const struct nvkm_gpuobj_func 144static const struct nvkm_gpuobj_func
@@ -125,6 +146,7 @@ nvkm_gpuobj_slow = {
125 .release = nvkm_gpuobj_release, 146 .release = nvkm_gpuobj_release,
126 .rd32 = nvkm_gpuobj_rd32, 147 .rd32 = nvkm_gpuobj_rd32,
127 .wr32 = nvkm_gpuobj_wr32, 148 .wr32 = nvkm_gpuobj_wr32,
149 .map = nvkm_gpuobj_map,
128}; 150};
129 151
130static void * 152static void *
@@ -143,6 +165,7 @@ nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj)
143static const struct nvkm_gpuobj_func 165static const struct nvkm_gpuobj_func
144nvkm_gpuobj_func = { 166nvkm_gpuobj_func = {
145 .acquire = nvkm_gpuobj_acquire, 167 .acquire = nvkm_gpuobj_acquire,
168 .map = nvkm_gpuobj_map,
146}; 169};
147 170
148static int 171static int
@@ -185,7 +208,7 @@ nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero,
185 gpuobj->size = nvkm_memory_size(gpuobj->memory); 208 gpuobj->size = nvkm_memory_size(gpuobj->memory);
186 } 209 }
187 210
188 return nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); 211 return nvkm_mm_init(&gpuobj->heap, 0, 0, gpuobj->size, 1);
189} 212}
190 213
191void 214void
@@ -196,7 +219,7 @@ nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj)
196 if (gpuobj->parent) 219 if (gpuobj->parent)
197 nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); 220 nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node);
198 nvkm_mm_fini(&gpuobj->heap); 221 nvkm_mm_fini(&gpuobj->heap);
199 nvkm_memory_del(&gpuobj->memory); 222 nvkm_memory_unref(&gpuobj->memory);
200 kfree(*pgpuobj); 223 kfree(*pgpuobj);
201 *pgpuobj = NULL; 224 *pgpuobj = NULL;
202 } 225 }
@@ -218,26 +241,6 @@ nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero,
218 return ret; 241 return ret;
219} 242}
220 243
221int
222nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm,
223 u32 access, struct nvkm_vma *vma)
224{
225 struct nvkm_memory *memory = gpuobj->memory;
226 int ret = nvkm_vm_get(vm, gpuobj->size, 12, access, vma);
227 if (ret == 0)
228 nvkm_memory_map(memory, vma, 0);
229 return ret;
230}
231
232void
233nvkm_gpuobj_unmap(struct nvkm_vma *vma)
234{
235 if (vma->node) {
236 nvkm_vm_unmap(vma);
237 nvkm_vm_put(vma);
238 }
239}
240
241/* the below is basically only here to support sharing the paged dma object 244/* the below is basically only here to support sharing the paged dma object
242 * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work 245 * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work
243 * anywhere else. 246 * anywhere else.
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index be19bbe56bba..d777df5a64e6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -53,7 +53,7 @@ nvkm_ioctl_sclass(struct nvkm_client *client,
53 union { 53 union {
54 struct nvif_ioctl_sclass_v0 v0; 54 struct nvif_ioctl_sclass_v0 v0;
55 } *args = data; 55 } *args = data;
56 struct nvkm_oclass oclass; 56 struct nvkm_oclass oclass = { .client = client };
57 int ret = -ENOSYS, i = 0; 57 int ret = -ENOSYS, i = 0;
58 58
59 nvif_ioctl(object, "sclass size %d\n", size); 59 nvif_ioctl(object, "sclass size %d\n", size);
@@ -257,13 +257,19 @@ nvkm_ioctl_map(struct nvkm_client *client,
257 union { 257 union {
258 struct nvif_ioctl_map_v0 v0; 258 struct nvif_ioctl_map_v0 v0;
259 } *args = data; 259 } *args = data;
260 enum nvkm_object_map type;
260 int ret = -ENOSYS; 261 int ret = -ENOSYS;
261 262
262 nvif_ioctl(object, "map size %d\n", size); 263 nvif_ioctl(object, "map size %d\n", size);
263 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 264 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
264 nvif_ioctl(object, "map vers %d\n", args->v0.version); 265 nvif_ioctl(object, "map vers %d\n", args->v0.version);
265 ret = nvkm_object_map(object, &args->v0.handle, 266 ret = nvkm_object_map(object, data, size, &type,
266 &args->v0.length); 267 &args->v0.handle,
268 &args->v0.length);
269 if (type == NVKM_OBJECT_MAP_IO)
270 args->v0.type = NVIF_IOCTL_MAP_V0_IO;
271 else
272 args->v0.type = NVIF_IOCTL_MAP_V0_VA;
267 } 273 }
268 274
269 return ret; 275 return ret;
@@ -281,6 +287,7 @@ nvkm_ioctl_unmap(struct nvkm_client *client,
281 nvif_ioctl(object, "unmap size %d\n", size); 287 nvif_ioctl(object, "unmap size %d\n", size);
282 if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { 288 if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
283 nvif_ioctl(object, "unmap\n"); 289 nvif_ioctl(object, "unmap\n");
290 ret = nvkm_object_unmap(object);
284 } 291 }
285 292
286 return ret; 293 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/memory.c b/drivers/gpu/drm/nouveau/nvkm/core/memory.c
index 8903c04c977e..29f4b4070b55 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/memory.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/memory.c
@@ -22,27 +22,116 @@
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24#include <core/memory.h> 24#include <core/memory.h>
25#include <core/mm.h>
26#include <subdev/fb.h>
25#include <subdev/instmem.h> 27#include <subdev/instmem.h>
26 28
27void 29void
30nvkm_memory_tags_put(struct nvkm_memory *memory, struct nvkm_device *device,
31 struct nvkm_tags **ptags)
32{
33 struct nvkm_fb *fb = device->fb;
34 struct nvkm_tags *tags = *ptags;
35 if (tags) {
36 mutex_lock(&fb->subdev.mutex);
37 if (refcount_dec_and_test(&tags->refcount)) {
38 nvkm_mm_free(&fb->tags, &tags->mn);
39 kfree(memory->tags);
40 memory->tags = NULL;
41 }
42 mutex_unlock(&fb->subdev.mutex);
43 *ptags = NULL;
44 }
45}
46
47int
48nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device,
49 u32 nr, void (*clr)(struct nvkm_device *, u32, u32),
50 struct nvkm_tags **ptags)
51{
52 struct nvkm_fb *fb = device->fb;
53 struct nvkm_tags *tags;
54
55 mutex_lock(&fb->subdev.mutex);
56 if ((tags = memory->tags)) {
57 /* If comptags exist for the memory, but a different amount
58 * than requested, the buffer is being mapped with settings
59 * that are incompatible with existing mappings.
60 */
61 if (tags->mn && tags->mn->length != nr) {
62 mutex_unlock(&fb->subdev.mutex);
63 return -EINVAL;
64 }
65
66 refcount_inc(&tags->refcount);
67 *ptags = tags;
68 return 0;
69 }
70
71 if (!(tags = kmalloc(sizeof(*tags), GFP_KERNEL))) {
72 mutex_unlock(&fb->subdev.mutex);
73 return -ENOMEM;
74 }
75
76 if (!nvkm_mm_head(&fb->tags, 0, 1, nr, nr, 1, &tags->mn)) {
77 if (clr)
78 clr(device, tags->mn->offset, tags->mn->length);
79 } else {
80 /* Failure to allocate HW comptags is not an error, the
81 * caller should fall back to an uncompressed map.
82 *
83 * As memory can be mapped in multiple places, we still
84 * need to track the allocation failure and ensure that
85 * any additional mappings remain uncompressed.
86 *
87 * This is handled by returning an empty nvkm_tags.
88 */
89 tags->mn = NULL;
90 }
91
92 refcount_set(&tags->refcount, 1);
93 mutex_unlock(&fb->subdev.mutex);
94 *ptags = tags;
95 return 0;
96}
97
98void
28nvkm_memory_ctor(const struct nvkm_memory_func *func, 99nvkm_memory_ctor(const struct nvkm_memory_func *func,
29 struct nvkm_memory *memory) 100 struct nvkm_memory *memory)
30{ 101{
31 memory->func = func; 102 memory->func = func;
103 kref_init(&memory->kref);
104}
105
106static void
107nvkm_memory_del(struct kref *kref)
108{
109 struct nvkm_memory *memory = container_of(kref, typeof(*memory), kref);
110 if (!WARN_ON(!memory->func)) {
111 if (memory->func->dtor)
112 memory = memory->func->dtor(memory);
113 kfree(memory);
114 }
32} 115}
33 116
34void 117void
35nvkm_memory_del(struct nvkm_memory **pmemory) 118nvkm_memory_unref(struct nvkm_memory **pmemory)
36{ 119{
37 struct nvkm_memory *memory = *pmemory; 120 struct nvkm_memory *memory = *pmemory;
38 if (memory && !WARN_ON(!memory->func)) { 121 if (memory) {
39 if (memory->func->dtor) 122 kref_put(&memory->kref, nvkm_memory_del);
40 *pmemory = memory->func->dtor(memory);
41 kfree(*pmemory);
42 *pmemory = NULL; 123 *pmemory = NULL;
43 } 124 }
44} 125}
45 126
127struct nvkm_memory *
128nvkm_memory_ref(struct nvkm_memory *memory)
129{
130 if (memory)
131 kref_get(&memory->kref);
132 return memory;
133}
134
46int 135int
47nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target, 136nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target,
48 u64 size, u32 align, bool zero, 137 u64 size, u32 align, bool zero,
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/mm.c b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
index 5c7891234eea..f78a06a6b2f1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/mm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/mm.c
@@ -237,7 +237,7 @@ nvkm_mm_tail(struct nvkm_mm *mm, u8 heap, u8 type, u32 size_max, u32 size_min,
237} 237}
238 238
239int 239int
240nvkm_mm_init(struct nvkm_mm *mm, u32 offset, u32 length, u32 block) 240nvkm_mm_init(struct nvkm_mm *mm, u8 heap, u32 offset, u32 length, u32 block)
241{ 241{
242 struct nvkm_mm_node *node, *prev; 242 struct nvkm_mm_node *node, *prev;
243 u32 next; 243 u32 next;
@@ -274,7 +274,8 @@ nvkm_mm_init(struct nvkm_mm *mm, u32 offset, u32 length, u32 block)
274 274
275 list_add_tail(&node->nl_entry, &mm->nodes); 275 list_add_tail(&node->nl_entry, &mm->nodes);
276 list_add_tail(&node->fl_entry, &mm->free); 276 list_add_tail(&node->fl_entry, &mm->free);
277 node->heap = ++mm->heap_nodes; 277 node->heap = heap;
278 mm->heap_nodes++;
278 return 0; 279 return 0;
279} 280}
280 281
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c
index acd76fd4f6d8..301a5e5b5f7f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
@@ -102,10 +102,19 @@ nvkm_object_ntfy(struct nvkm_object *object, u32 mthd,
102} 102}
103 103
104int 104int
105nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size) 105nvkm_object_map(struct nvkm_object *object, void *argv, u32 argc,
106 enum nvkm_object_map *type, u64 *addr, u64 *size)
106{ 107{
107 if (likely(object->func->map)) 108 if (likely(object->func->map))
108 return object->func->map(object, addr, size); 109 return object->func->map(object, argv, argc, type, addr, size);
110 return -ENODEV;
111}
112
113int
114nvkm_object_unmap(struct nvkm_object *object)
115{
116 if (likely(object->func->unmap))
117 return object->func->unmap(object);
109 return -ENODEV; 118 return -ENODEV;
110} 119}
111 120
@@ -259,6 +268,7 @@ nvkm_object_dtor(struct nvkm_object *object)
259 } 268 }
260 269
261 nvif_debug(object, "destroy running...\n"); 270 nvif_debug(object, "destroy running...\n");
271 nvkm_object_unmap(object);
262 if (object->func->dtor) 272 if (object->func->dtor)
263 data = object->func->dtor(object); 273 data = object->func->dtor(object);
264 nvkm_engine_unref(&object->engine); 274 nvkm_engine_unref(&object->engine);
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
index e31a0479add0..16299837a296 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
@@ -37,9 +37,17 @@ nvkm_oproxy_ntfy(struct nvkm_object *object, u32 mthd,
37} 37}
38 38
39static int 39static int
40nvkm_oproxy_map(struct nvkm_object *object, u64 *addr, u32 *size) 40nvkm_oproxy_map(struct nvkm_object *object, void *argv, u32 argc,
41 enum nvkm_object_map *type, u64 *addr, u64 *size)
41{ 42{
42 return nvkm_object_map(nvkm_oproxy(object)->object, addr, size); 43 struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
44 return nvkm_object_map(oproxy->object, argv, argc, type, addr, size);
45}
46
47static int
48nvkm_oproxy_unmap(struct nvkm_object *object)
49{
50 return nvkm_object_unmap(nvkm_oproxy(object)->object);
43} 51}
44 52
45static int 53static int
@@ -171,6 +179,7 @@ nvkm_oproxy_func = {
171 .mthd = nvkm_oproxy_mthd, 179 .mthd = nvkm_oproxy_mthd,
172 .ntfy = nvkm_oproxy_ntfy, 180 .ntfy = nvkm_oproxy_ntfy,
173 .map = nvkm_oproxy_map, 181 .map = nvkm_oproxy_map,
182 .unmap = nvkm_oproxy_unmap,
174 .rd08 = nvkm_oproxy_rd08, 183 .rd08 = nvkm_oproxy_rd08,
175 .rd16 = nvkm_oproxy_rd16, 184 .rd16 = nvkm_oproxy_rd16,
176 .rd32 = nvkm_oproxy_rd32, 185 .rd32 = nvkm_oproxy_rd32,
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
index 89da47234016..ccba4ae73cc5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c
@@ -21,6 +21,7 @@
21 */ 21 */
22#include <core/ramht.h> 22#include <core/ramht.h>
23#include <core/engine.h> 23#include <core/engine.h>
24#include <core/object.h>
24 25
25static u32 26static u32
26nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) 27nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index e096a5d9c292..e14643615698 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -927,7 +927,7 @@ nv84_chipset = {
927 .i2c = nv50_i2c_new, 927 .i2c = nv50_i2c_new,
928 .imem = nv50_instmem_new, 928 .imem = nv50_instmem_new,
929 .mc = g84_mc_new, 929 .mc = g84_mc_new,
930 .mmu = nv50_mmu_new, 930 .mmu = g84_mmu_new,
931 .mxm = nv50_mxm_new, 931 .mxm = nv50_mxm_new,
932 .pci = g84_pci_new, 932 .pci = g84_pci_new,
933 .therm = g84_therm_new, 933 .therm = g84_therm_new,
@@ -959,7 +959,7 @@ nv86_chipset = {
959 .i2c = nv50_i2c_new, 959 .i2c = nv50_i2c_new,
960 .imem = nv50_instmem_new, 960 .imem = nv50_instmem_new,
961 .mc = g84_mc_new, 961 .mc = g84_mc_new,
962 .mmu = nv50_mmu_new, 962 .mmu = g84_mmu_new,
963 .mxm = nv50_mxm_new, 963 .mxm = nv50_mxm_new,
964 .pci = g84_pci_new, 964 .pci = g84_pci_new,
965 .therm = g84_therm_new, 965 .therm = g84_therm_new,
@@ -991,7 +991,7 @@ nv92_chipset = {
991 .i2c = nv50_i2c_new, 991 .i2c = nv50_i2c_new,
992 .imem = nv50_instmem_new, 992 .imem = nv50_instmem_new,
993 .mc = g84_mc_new, 993 .mc = g84_mc_new,
994 .mmu = nv50_mmu_new, 994 .mmu = g84_mmu_new,
995 .mxm = nv50_mxm_new, 995 .mxm = nv50_mxm_new,
996 .pci = g92_pci_new, 996 .pci = g92_pci_new,
997 .therm = g84_therm_new, 997 .therm = g84_therm_new,
@@ -1023,7 +1023,7 @@ nv94_chipset = {
1023 .i2c = g94_i2c_new, 1023 .i2c = g94_i2c_new,
1024 .imem = nv50_instmem_new, 1024 .imem = nv50_instmem_new,
1025 .mc = g84_mc_new, 1025 .mc = g84_mc_new,
1026 .mmu = nv50_mmu_new, 1026 .mmu = g84_mmu_new,
1027 .mxm = nv50_mxm_new, 1027 .mxm = nv50_mxm_new,
1028 .pci = g94_pci_new, 1028 .pci = g94_pci_new,
1029 .therm = g84_therm_new, 1029 .therm = g84_therm_new,
@@ -1055,7 +1055,7 @@ nv96_chipset = {
1055 .i2c = g94_i2c_new, 1055 .i2c = g94_i2c_new,
1056 .imem = nv50_instmem_new, 1056 .imem = nv50_instmem_new,
1057 .mc = g84_mc_new, 1057 .mc = g84_mc_new,
1058 .mmu = nv50_mmu_new, 1058 .mmu = g84_mmu_new,
1059 .mxm = nv50_mxm_new, 1059 .mxm = nv50_mxm_new,
1060 .pci = g94_pci_new, 1060 .pci = g94_pci_new,
1061 .therm = g84_therm_new, 1061 .therm = g84_therm_new,
@@ -1087,7 +1087,7 @@ nv98_chipset = {
1087 .i2c = g94_i2c_new, 1087 .i2c = g94_i2c_new,
1088 .imem = nv50_instmem_new, 1088 .imem = nv50_instmem_new,
1089 .mc = g98_mc_new, 1089 .mc = g98_mc_new,
1090 .mmu = nv50_mmu_new, 1090 .mmu = g84_mmu_new,
1091 .mxm = nv50_mxm_new, 1091 .mxm = nv50_mxm_new,
1092 .pci = g94_pci_new, 1092 .pci = g94_pci_new,
1093 .therm = g84_therm_new, 1093 .therm = g84_therm_new,
@@ -1119,7 +1119,7 @@ nva0_chipset = {
1119 .i2c = nv50_i2c_new, 1119 .i2c = nv50_i2c_new,
1120 .imem = nv50_instmem_new, 1120 .imem = nv50_instmem_new,
1121 .mc = g84_mc_new, 1121 .mc = g84_mc_new,
1122 .mmu = nv50_mmu_new, 1122 .mmu = g84_mmu_new,
1123 .mxm = nv50_mxm_new, 1123 .mxm = nv50_mxm_new,
1124 .pci = g94_pci_new, 1124 .pci = g94_pci_new,
1125 .therm = g84_therm_new, 1125 .therm = g84_therm_new,
@@ -1151,7 +1151,7 @@ nva3_chipset = {
1151 .i2c = g94_i2c_new, 1151 .i2c = g94_i2c_new,
1152 .imem = nv50_instmem_new, 1152 .imem = nv50_instmem_new,
1153 .mc = gt215_mc_new, 1153 .mc = gt215_mc_new,
1154 .mmu = nv50_mmu_new, 1154 .mmu = g84_mmu_new,
1155 .mxm = nv50_mxm_new, 1155 .mxm = nv50_mxm_new,
1156 .pci = g94_pci_new, 1156 .pci = g94_pci_new,
1157 .pmu = gt215_pmu_new, 1157 .pmu = gt215_pmu_new,
@@ -1185,7 +1185,7 @@ nva5_chipset = {
1185 .i2c = g94_i2c_new, 1185 .i2c = g94_i2c_new,
1186 .imem = nv50_instmem_new, 1186 .imem = nv50_instmem_new,
1187 .mc = gt215_mc_new, 1187 .mc = gt215_mc_new,
1188 .mmu = nv50_mmu_new, 1188 .mmu = g84_mmu_new,
1189 .mxm = nv50_mxm_new, 1189 .mxm = nv50_mxm_new,
1190 .pci = g94_pci_new, 1190 .pci = g94_pci_new,
1191 .pmu = gt215_pmu_new, 1191 .pmu = gt215_pmu_new,
@@ -1218,7 +1218,7 @@ nva8_chipset = {
1218 .i2c = g94_i2c_new, 1218 .i2c = g94_i2c_new,
1219 .imem = nv50_instmem_new, 1219 .imem = nv50_instmem_new,
1220 .mc = gt215_mc_new, 1220 .mc = gt215_mc_new,
1221 .mmu = nv50_mmu_new, 1221 .mmu = g84_mmu_new,
1222 .mxm = nv50_mxm_new, 1222 .mxm = nv50_mxm_new,
1223 .pci = g94_pci_new, 1223 .pci = g94_pci_new,
1224 .pmu = gt215_pmu_new, 1224 .pmu = gt215_pmu_new,
@@ -1251,7 +1251,7 @@ nvaa_chipset = {
1251 .i2c = g94_i2c_new, 1251 .i2c = g94_i2c_new,
1252 .imem = nv50_instmem_new, 1252 .imem = nv50_instmem_new,
1253 .mc = g98_mc_new, 1253 .mc = g98_mc_new,
1254 .mmu = nv50_mmu_new, 1254 .mmu = g84_mmu_new,
1255 .mxm = nv50_mxm_new, 1255 .mxm = nv50_mxm_new,
1256 .pci = g94_pci_new, 1256 .pci = g94_pci_new,
1257 .therm = g84_therm_new, 1257 .therm = g84_therm_new,
@@ -1283,7 +1283,7 @@ nvac_chipset = {
1283 .i2c = g94_i2c_new, 1283 .i2c = g94_i2c_new,
1284 .imem = nv50_instmem_new, 1284 .imem = nv50_instmem_new,
1285 .mc = g98_mc_new, 1285 .mc = g98_mc_new,
1286 .mmu = nv50_mmu_new, 1286 .mmu = g84_mmu_new,
1287 .mxm = nv50_mxm_new, 1287 .mxm = nv50_mxm_new,
1288 .pci = g94_pci_new, 1288 .pci = g94_pci_new,
1289 .therm = g84_therm_new, 1289 .therm = g84_therm_new,
@@ -1315,7 +1315,7 @@ nvaf_chipset = {
1315 .i2c = g94_i2c_new, 1315 .i2c = g94_i2c_new,
1316 .imem = nv50_instmem_new, 1316 .imem = nv50_instmem_new,
1317 .mc = gt215_mc_new, 1317 .mc = gt215_mc_new,
1318 .mmu = nv50_mmu_new, 1318 .mmu = g84_mmu_new,
1319 .mxm = nv50_mxm_new, 1319 .mxm = nv50_mxm_new,
1320 .pci = g94_pci_new, 1320 .pci = g94_pci_new,
1321 .pmu = gt215_pmu_new, 1321 .pmu = gt215_pmu_new,
@@ -1678,7 +1678,7 @@ nve4_chipset = {
1678 .imem = nv50_instmem_new, 1678 .imem = nv50_instmem_new,
1679 .ltc = gk104_ltc_new, 1679 .ltc = gk104_ltc_new,
1680 .mc = gk104_mc_new, 1680 .mc = gk104_mc_new,
1681 .mmu = gf100_mmu_new, 1681 .mmu = gk104_mmu_new,
1682 .mxm = nv50_mxm_new, 1682 .mxm = nv50_mxm_new,
1683 .pci = gk104_pci_new, 1683 .pci = gk104_pci_new,
1684 .pmu = gk104_pmu_new, 1684 .pmu = gk104_pmu_new,
@@ -1717,7 +1717,7 @@ nve6_chipset = {
1717 .imem = nv50_instmem_new, 1717 .imem = nv50_instmem_new,
1718 .ltc = gk104_ltc_new, 1718 .ltc = gk104_ltc_new,
1719 .mc = gk104_mc_new, 1719 .mc = gk104_mc_new,
1720 .mmu = gf100_mmu_new, 1720 .mmu = gk104_mmu_new,
1721 .mxm = nv50_mxm_new, 1721 .mxm = nv50_mxm_new,
1722 .pci = gk104_pci_new, 1722 .pci = gk104_pci_new,
1723 .pmu = gk104_pmu_new, 1723 .pmu = gk104_pmu_new,
@@ -1756,7 +1756,7 @@ nve7_chipset = {
1756 .imem = nv50_instmem_new, 1756 .imem = nv50_instmem_new,
1757 .ltc = gk104_ltc_new, 1757 .ltc = gk104_ltc_new,
1758 .mc = gk104_mc_new, 1758 .mc = gk104_mc_new,
1759 .mmu = gf100_mmu_new, 1759 .mmu = gk104_mmu_new,
1760 .mxm = nv50_mxm_new, 1760 .mxm = nv50_mxm_new,
1761 .pci = gk104_pci_new, 1761 .pci = gk104_pci_new,
1762 .pmu = gk104_pmu_new, 1762 .pmu = gk104_pmu_new,
@@ -1790,7 +1790,7 @@ nvea_chipset = {
1790 .imem = gk20a_instmem_new, 1790 .imem = gk20a_instmem_new,
1791 .ltc = gk104_ltc_new, 1791 .ltc = gk104_ltc_new,
1792 .mc = gk20a_mc_new, 1792 .mc = gk20a_mc_new,
1793 .mmu = gf100_mmu_new, 1793 .mmu = gk20a_mmu_new,
1794 .pmu = gk20a_pmu_new, 1794 .pmu = gk20a_pmu_new,
1795 .timer = gk20a_timer_new, 1795 .timer = gk20a_timer_new,
1796 .top = gk104_top_new, 1796 .top = gk104_top_new,
@@ -1820,7 +1820,7 @@ nvf0_chipset = {
1820 .imem = nv50_instmem_new, 1820 .imem = nv50_instmem_new,
1821 .ltc = gk104_ltc_new, 1821 .ltc = gk104_ltc_new,
1822 .mc = gk104_mc_new, 1822 .mc = gk104_mc_new,
1823 .mmu = gf100_mmu_new, 1823 .mmu = gk104_mmu_new,
1824 .mxm = nv50_mxm_new, 1824 .mxm = nv50_mxm_new,
1825 .pci = gk104_pci_new, 1825 .pci = gk104_pci_new,
1826 .pmu = gk110_pmu_new, 1826 .pmu = gk110_pmu_new,
@@ -1858,7 +1858,7 @@ nvf1_chipset = {
1858 .imem = nv50_instmem_new, 1858 .imem = nv50_instmem_new,
1859 .ltc = gk104_ltc_new, 1859 .ltc = gk104_ltc_new,
1860 .mc = gk104_mc_new, 1860 .mc = gk104_mc_new,
1861 .mmu = gf100_mmu_new, 1861 .mmu = gk104_mmu_new,
1862 .mxm = nv50_mxm_new, 1862 .mxm = nv50_mxm_new,
1863 .pci = gk104_pci_new, 1863 .pci = gk104_pci_new,
1864 .pmu = gk110_pmu_new, 1864 .pmu = gk110_pmu_new,
@@ -1896,7 +1896,7 @@ nv106_chipset = {
1896 .imem = nv50_instmem_new, 1896 .imem = nv50_instmem_new,
1897 .ltc = gk104_ltc_new, 1897 .ltc = gk104_ltc_new,
1898 .mc = gk20a_mc_new, 1898 .mc = gk20a_mc_new,
1899 .mmu = gf100_mmu_new, 1899 .mmu = gk104_mmu_new,
1900 .mxm = nv50_mxm_new, 1900 .mxm = nv50_mxm_new,
1901 .pci = gk104_pci_new, 1901 .pci = gk104_pci_new,
1902 .pmu = gk208_pmu_new, 1902 .pmu = gk208_pmu_new,
@@ -1934,7 +1934,7 @@ nv108_chipset = {
1934 .imem = nv50_instmem_new, 1934 .imem = nv50_instmem_new,
1935 .ltc = gk104_ltc_new, 1935 .ltc = gk104_ltc_new,
1936 .mc = gk20a_mc_new, 1936 .mc = gk20a_mc_new,
1937 .mmu = gf100_mmu_new, 1937 .mmu = gk104_mmu_new,
1938 .mxm = nv50_mxm_new, 1938 .mxm = nv50_mxm_new,
1939 .pci = gk104_pci_new, 1939 .pci = gk104_pci_new,
1940 .pmu = gk208_pmu_new, 1940 .pmu = gk208_pmu_new,
@@ -1958,7 +1958,7 @@ nv108_chipset = {
1958static const struct nvkm_device_chip 1958static const struct nvkm_device_chip
1959nv117_chipset = { 1959nv117_chipset = {
1960 .name = "GM107", 1960 .name = "GM107",
1961 .bar = gf100_bar_new, 1961 .bar = gm107_bar_new,
1962 .bios = nvkm_bios_new, 1962 .bios = nvkm_bios_new,
1963 .bus = gf100_bus_new, 1963 .bus = gf100_bus_new,
1964 .clk = gk104_clk_new, 1964 .clk = gk104_clk_new,
@@ -1972,7 +1972,7 @@ nv117_chipset = {
1972 .imem = nv50_instmem_new, 1972 .imem = nv50_instmem_new,
1973 .ltc = gm107_ltc_new, 1973 .ltc = gm107_ltc_new,
1974 .mc = gk20a_mc_new, 1974 .mc = gk20a_mc_new,
1975 .mmu = gf100_mmu_new, 1975 .mmu = gk104_mmu_new,
1976 .mxm = nv50_mxm_new, 1976 .mxm = nv50_mxm_new,
1977 .pci = gk104_pci_new, 1977 .pci = gk104_pci_new,
1978 .pmu = gm107_pmu_new, 1978 .pmu = gm107_pmu_new,
@@ -1992,7 +1992,7 @@ nv117_chipset = {
1992static const struct nvkm_device_chip 1992static const struct nvkm_device_chip
1993nv118_chipset = { 1993nv118_chipset = {
1994 .name = "GM108", 1994 .name = "GM108",
1995 .bar = gf100_bar_new, 1995 .bar = gm107_bar_new,
1996 .bios = nvkm_bios_new, 1996 .bios = nvkm_bios_new,
1997 .bus = gf100_bus_new, 1997 .bus = gf100_bus_new,
1998 .clk = gk104_clk_new, 1998 .clk = gk104_clk_new,
@@ -2006,7 +2006,7 @@ nv118_chipset = {
2006 .imem = nv50_instmem_new, 2006 .imem = nv50_instmem_new,
2007 .ltc = gm107_ltc_new, 2007 .ltc = gm107_ltc_new,
2008 .mc = gk20a_mc_new, 2008 .mc = gk20a_mc_new,
2009 .mmu = gf100_mmu_new, 2009 .mmu = gk104_mmu_new,
2010 .mxm = nv50_mxm_new, 2010 .mxm = nv50_mxm_new,
2011 .pci = gk104_pci_new, 2011 .pci = gk104_pci_new,
2012 .pmu = gm107_pmu_new, 2012 .pmu = gm107_pmu_new,
@@ -2026,7 +2026,7 @@ nv118_chipset = {
2026static const struct nvkm_device_chip 2026static const struct nvkm_device_chip
2027nv120_chipset = { 2027nv120_chipset = {
2028 .name = "GM200", 2028 .name = "GM200",
2029 .bar = gf100_bar_new, 2029 .bar = gm107_bar_new,
2030 .bios = nvkm_bios_new, 2030 .bios = nvkm_bios_new,
2031 .bus = gf100_bus_new, 2031 .bus = gf100_bus_new,
2032 .devinit = gm200_devinit_new, 2032 .devinit = gm200_devinit_new,
@@ -2039,7 +2039,7 @@ nv120_chipset = {
2039 .imem = nv50_instmem_new, 2039 .imem = nv50_instmem_new,
2040 .ltc = gm200_ltc_new, 2040 .ltc = gm200_ltc_new,
2041 .mc = gk20a_mc_new, 2041 .mc = gk20a_mc_new,
2042 .mmu = gf100_mmu_new, 2042 .mmu = gm200_mmu_new,
2043 .mxm = nv50_mxm_new, 2043 .mxm = nv50_mxm_new,
2044 .pci = gk104_pci_new, 2044 .pci = gk104_pci_new,
2045 .pmu = gm107_pmu_new, 2045 .pmu = gm107_pmu_new,
@@ -2061,7 +2061,7 @@ nv120_chipset = {
2061static const struct nvkm_device_chip 2061static const struct nvkm_device_chip
2062nv124_chipset = { 2062nv124_chipset = {
2063 .name = "GM204", 2063 .name = "GM204",
2064 .bar = gf100_bar_new, 2064 .bar = gm107_bar_new,
2065 .bios = nvkm_bios_new, 2065 .bios = nvkm_bios_new,
2066 .bus = gf100_bus_new, 2066 .bus = gf100_bus_new,
2067 .devinit = gm200_devinit_new, 2067 .devinit = gm200_devinit_new,
@@ -2074,7 +2074,7 @@ nv124_chipset = {
2074 .imem = nv50_instmem_new, 2074 .imem = nv50_instmem_new,
2075 .ltc = gm200_ltc_new, 2075 .ltc = gm200_ltc_new,
2076 .mc = gk20a_mc_new, 2076 .mc = gk20a_mc_new,
2077 .mmu = gf100_mmu_new, 2077 .mmu = gm200_mmu_new,
2078 .mxm = nv50_mxm_new, 2078 .mxm = nv50_mxm_new,
2079 .pci = gk104_pci_new, 2079 .pci = gk104_pci_new,
2080 .pmu = gm107_pmu_new, 2080 .pmu = gm107_pmu_new,
@@ -2096,7 +2096,7 @@ nv124_chipset = {
2096static const struct nvkm_device_chip 2096static const struct nvkm_device_chip
2097nv126_chipset = { 2097nv126_chipset = {
2098 .name = "GM206", 2098 .name = "GM206",
2099 .bar = gf100_bar_new, 2099 .bar = gm107_bar_new,
2100 .bios = nvkm_bios_new, 2100 .bios = nvkm_bios_new,
2101 .bus = gf100_bus_new, 2101 .bus = gf100_bus_new,
2102 .devinit = gm200_devinit_new, 2102 .devinit = gm200_devinit_new,
@@ -2109,7 +2109,7 @@ nv126_chipset = {
2109 .imem = nv50_instmem_new, 2109 .imem = nv50_instmem_new,
2110 .ltc = gm200_ltc_new, 2110 .ltc = gm200_ltc_new,
2111 .mc = gk20a_mc_new, 2111 .mc = gk20a_mc_new,
2112 .mmu = gf100_mmu_new, 2112 .mmu = gm200_mmu_new,
2113 .mxm = nv50_mxm_new, 2113 .mxm = nv50_mxm_new,
2114 .pci = gk104_pci_new, 2114 .pci = gk104_pci_new,
2115 .pmu = gm107_pmu_new, 2115 .pmu = gm107_pmu_new,
@@ -2131,7 +2131,7 @@ nv126_chipset = {
2131static const struct nvkm_device_chip 2131static const struct nvkm_device_chip
2132nv12b_chipset = { 2132nv12b_chipset = {
2133 .name = "GM20B", 2133 .name = "GM20B",
2134 .bar = gk20a_bar_new, 2134 .bar = gm20b_bar_new,
2135 .bus = gf100_bus_new, 2135 .bus = gf100_bus_new,
2136 .clk = gm20b_clk_new, 2136 .clk = gm20b_clk_new,
2137 .fb = gm20b_fb_new, 2137 .fb = gm20b_fb_new,
@@ -2140,7 +2140,7 @@ nv12b_chipset = {
2140 .imem = gk20a_instmem_new, 2140 .imem = gk20a_instmem_new,
2141 .ltc = gm200_ltc_new, 2141 .ltc = gm200_ltc_new,
2142 .mc = gk20a_mc_new, 2142 .mc = gk20a_mc_new,
2143 .mmu = gf100_mmu_new, 2143 .mmu = gm20b_mmu_new,
2144 .pmu = gm20b_pmu_new, 2144 .pmu = gm20b_pmu_new,
2145 .secboot = gm20b_secboot_new, 2145 .secboot = gm20b_secboot_new,
2146 .timer = gk20a_timer_new, 2146 .timer = gk20a_timer_new,
@@ -2156,7 +2156,7 @@ nv12b_chipset = {
2156static const struct nvkm_device_chip 2156static const struct nvkm_device_chip
2157nv130_chipset = { 2157nv130_chipset = {
2158 .name = "GP100", 2158 .name = "GP100",
2159 .bar = gf100_bar_new, 2159 .bar = gm107_bar_new,
2160 .bios = nvkm_bios_new, 2160 .bios = nvkm_bios_new,
2161 .bus = gf100_bus_new, 2161 .bus = gf100_bus_new,
2162 .devinit = gm200_devinit_new, 2162 .devinit = gm200_devinit_new,
@@ -2168,7 +2168,8 @@ nv130_chipset = {
2168 .imem = nv50_instmem_new, 2168 .imem = nv50_instmem_new,
2169 .ltc = gp100_ltc_new, 2169 .ltc = gp100_ltc_new,
2170 .mc = gp100_mc_new, 2170 .mc = gp100_mc_new,
2171 .mmu = gf100_mmu_new, 2171 .mmu = gp100_mmu_new,
2172 .therm = gp100_therm_new,
2172 .secboot = gm200_secboot_new, 2173 .secboot = gm200_secboot_new,
2173 .pci = gp100_pci_new, 2174 .pci = gp100_pci_new,
2174 .pmu = gp100_pmu_new, 2175 .pmu = gp100_pmu_new,
@@ -2190,7 +2191,7 @@ nv130_chipset = {
2190static const struct nvkm_device_chip 2191static const struct nvkm_device_chip
2191nv132_chipset = { 2192nv132_chipset = {
2192 .name = "GP102", 2193 .name = "GP102",
2193 .bar = gf100_bar_new, 2194 .bar = gm107_bar_new,
2194 .bios = nvkm_bios_new, 2195 .bios = nvkm_bios_new,
2195 .bus = gf100_bus_new, 2196 .bus = gf100_bus_new,
2196 .devinit = gm200_devinit_new, 2197 .devinit = gm200_devinit_new,
@@ -2202,7 +2203,8 @@ nv132_chipset = {
2202 .imem = nv50_instmem_new, 2203 .imem = nv50_instmem_new,
2203 .ltc = gp100_ltc_new, 2204 .ltc = gp100_ltc_new,
2204 .mc = gp100_mc_new, 2205 .mc = gp100_mc_new,
2205 .mmu = gf100_mmu_new, 2206 .mmu = gp100_mmu_new,
2207 .therm = gp100_therm_new,
2206 .secboot = gp102_secboot_new, 2208 .secboot = gp102_secboot_new,
2207 .pci = gp100_pci_new, 2209 .pci = gp100_pci_new,
2208 .pmu = gp102_pmu_new, 2210 .pmu = gp102_pmu_new,
@@ -2224,7 +2226,7 @@ nv132_chipset = {
2224static const struct nvkm_device_chip 2226static const struct nvkm_device_chip
2225nv134_chipset = { 2227nv134_chipset = {
2226 .name = "GP104", 2228 .name = "GP104",
2227 .bar = gf100_bar_new, 2229 .bar = gm107_bar_new,
2228 .bios = nvkm_bios_new, 2230 .bios = nvkm_bios_new,
2229 .bus = gf100_bus_new, 2231 .bus = gf100_bus_new,
2230 .devinit = gm200_devinit_new, 2232 .devinit = gm200_devinit_new,
@@ -2236,7 +2238,8 @@ nv134_chipset = {
2236 .imem = nv50_instmem_new, 2238 .imem = nv50_instmem_new,
2237 .ltc = gp100_ltc_new, 2239 .ltc = gp100_ltc_new,
2238 .mc = gp100_mc_new, 2240 .mc = gp100_mc_new,
2239 .mmu = gf100_mmu_new, 2241 .mmu = gp100_mmu_new,
2242 .therm = gp100_therm_new,
2240 .secboot = gp102_secboot_new, 2243 .secboot = gp102_secboot_new,
2241 .pci = gp100_pci_new, 2244 .pci = gp100_pci_new,
2242 .pmu = gp102_pmu_new, 2245 .pmu = gp102_pmu_new,
@@ -2258,7 +2261,7 @@ nv134_chipset = {
2258static const struct nvkm_device_chip 2261static const struct nvkm_device_chip
2259nv136_chipset = { 2262nv136_chipset = {
2260 .name = "GP106", 2263 .name = "GP106",
2261 .bar = gf100_bar_new, 2264 .bar = gm107_bar_new,
2262 .bios = nvkm_bios_new, 2265 .bios = nvkm_bios_new,
2263 .bus = gf100_bus_new, 2266 .bus = gf100_bus_new,
2264 .devinit = gm200_devinit_new, 2267 .devinit = gm200_devinit_new,
@@ -2270,7 +2273,8 @@ nv136_chipset = {
2270 .imem = nv50_instmem_new, 2273 .imem = nv50_instmem_new,
2271 .ltc = gp100_ltc_new, 2274 .ltc = gp100_ltc_new,
2272 .mc = gp100_mc_new, 2275 .mc = gp100_mc_new,
2273 .mmu = gf100_mmu_new, 2276 .mmu = gp100_mmu_new,
2277 .therm = gp100_therm_new,
2274 .secboot = gp102_secboot_new, 2278 .secboot = gp102_secboot_new,
2275 .pci = gp100_pci_new, 2279 .pci = gp100_pci_new,
2276 .pmu = gp102_pmu_new, 2280 .pmu = gp102_pmu_new,
@@ -2292,7 +2296,7 @@ nv136_chipset = {
2292static const struct nvkm_device_chip 2296static const struct nvkm_device_chip
2293nv137_chipset = { 2297nv137_chipset = {
2294 .name = "GP107", 2298 .name = "GP107",
2295 .bar = gf100_bar_new, 2299 .bar = gm107_bar_new,
2296 .bios = nvkm_bios_new, 2300 .bios = nvkm_bios_new,
2297 .bus = gf100_bus_new, 2301 .bus = gf100_bus_new,
2298 .devinit = gm200_devinit_new, 2302 .devinit = gm200_devinit_new,
@@ -2304,7 +2308,8 @@ nv137_chipset = {
2304 .imem = nv50_instmem_new, 2308 .imem = nv50_instmem_new,
2305 .ltc = gp100_ltc_new, 2309 .ltc = gp100_ltc_new,
2306 .mc = gp100_mc_new, 2310 .mc = gp100_mc_new,
2307 .mmu = gf100_mmu_new, 2311 .mmu = gp100_mmu_new,
2312 .therm = gp100_therm_new,
2308 .secboot = gp102_secboot_new, 2313 .secboot = gp102_secboot_new,
2309 .pci = gp100_pci_new, 2314 .pci = gp100_pci_new,
2310 .pmu = gp102_pmu_new, 2315 .pmu = gp102_pmu_new,
@@ -2326,7 +2331,7 @@ nv137_chipset = {
2326static const struct nvkm_device_chip 2331static const struct nvkm_device_chip
2327nv138_chipset = { 2332nv138_chipset = {
2328 .name = "GP108", 2333 .name = "GP108",
2329 .bar = gf100_bar_new, 2334 .bar = gm107_bar_new,
2330 .bios = nvkm_bios_new, 2335 .bios = nvkm_bios_new,
2331 .bus = gf100_bus_new, 2336 .bus = gf100_bus_new,
2332 .devinit = gm200_devinit_new, 2337 .devinit = gm200_devinit_new,
@@ -2338,7 +2343,8 @@ nv138_chipset = {
2338 .imem = nv50_instmem_new, 2343 .imem = nv50_instmem_new,
2339 .ltc = gp100_ltc_new, 2344 .ltc = gp100_ltc_new,
2340 .mc = gp100_mc_new, 2345 .mc = gp100_mc_new,
2341 .mmu = gf100_mmu_new, 2346 .mmu = gp100_mmu_new,
2347 .therm = gp100_therm_new,
2342 .pci = gp100_pci_new, 2348 .pci = gp100_pci_new,
2343 .pmu = gp102_pmu_new, 2349 .pmu = gp102_pmu_new,
2344 .timer = gk20a_timer_new, 2350 .timer = gk20a_timer_new,
@@ -2355,7 +2361,7 @@ nv138_chipset = {
2355static const struct nvkm_device_chip 2361static const struct nvkm_device_chip
2356nv13b_chipset = { 2362nv13b_chipset = {
2357 .name = "GP10B", 2363 .name = "GP10B",
2358 .bar = gk20a_bar_new, 2364 .bar = gm20b_bar_new,
2359 .bus = gf100_bus_new, 2365 .bus = gf100_bus_new,
2360 .fb = gp10b_fb_new, 2366 .fb = gp10b_fb_new,
2361 .fuse = gm107_fuse_new, 2367 .fuse = gm107_fuse_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
index 20249d8e444d..2c3c3ee3c494 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h
@@ -1,7 +1,7 @@
1#ifndef __NVKM_DEVICE_CTRL_H__ 1#ifndef __NVKM_DEVICE_CTRL_H__
2#define __NVKM_DEVICE_CTRL_H__ 2#define __NVKM_DEVICE_CTRL_H__
3#define nvkm_control(p) container_of((p), struct nvkm_control, object) 3#define nvkm_control(p) container_of((p), struct nvkm_control, object)
4#include <core/device.h> 4#include <core/object.h>
5 5
6struct nvkm_control { 6struct nvkm_control {
7 struct nvkm_object object; 7 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index 74a1ffa425f7..f302d2b5782a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -1627,7 +1627,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
1627 const struct nvkm_device_pci_vendor *pciv; 1627 const struct nvkm_device_pci_vendor *pciv;
1628 const char *name = NULL; 1628 const char *name = NULL;
1629 struct nvkm_device_pci *pdev; 1629 struct nvkm_device_pci *pdev;
1630 int ret; 1630 int ret, bits;
1631 1631
1632 ret = pci_enable_device(pci_dev); 1632 ret = pci_enable_device(pci_dev);
1633 if (ret) 1633 if (ret)
@@ -1679,17 +1679,17 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
1679 if (ret) 1679 if (ret)
1680 return ret; 1680 return ret;
1681 1681
1682 /* 1682 /* Set DMA mask based on capabilities reported by the MMU subdev. */
1683 * Set a preliminary DMA mask based on the .dma_bits member of the 1683 if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
1684 * MMU subdevice. This allows other subdevices to create DMA mappings 1684 bits = pdev->device.mmu->dma_bits;
1685 * in their init() or oneinit() methods, which may be called before the 1685 else
1686 * TTM layer sets the DMA mask definitively. 1686 bits = 32;
1687 * This is necessary for platforms where the default DMA mask of 32 1687
1688 * does not cover any system memory, i.e., when all RAM is > 4 GB. 1688 ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits));
1689 */ 1689 if (ret && bits != 32) {
1690 if (pdev->device.mmu) 1690 dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
1691 dma_set_mask_and_coherent(&pci_dev->dev, 1691 pdev->device.mmu->dma_bits = 32;
1692 DMA_BIT_MASK(pdev->device.mmu->dma_bits)); 1692 }
1693 1693
1694 return 0; 1694 return 0;
1695} 1695}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index 189ed80e21ff..78597da6313a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -136,7 +136,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
136 if (ret) 136 if (ret)
137 goto free_domain; 137 goto free_domain;
138 138
139 ret = nvkm_mm_init(&tdev->iommu.mm, 0, 139 ret = nvkm_mm_init(&tdev->iommu.mm, 0, 0,
140 (1ULL << tdev->func->iommu_bit) >> 140 (1ULL << tdev->func->iommu_bit) >>
141 tdev->iommu.pgshift, 1); 141 tdev->iommu.pgshift, 1);
142 if (ret) 142 if (ret)
@@ -216,7 +216,7 @@ nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend)
216 if (tdev->irq) { 216 if (tdev->irq) {
217 free_irq(tdev->irq, tdev); 217 free_irq(tdev->irq, tdev);
218 tdev->irq = 0; 218 tdev->irq = 0;
219 }; 219 }
220} 220}
221 221
222static int 222static int
@@ -309,8 +309,6 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
309 309
310 /** 310 /**
311 * The IOMMU bit defines the upper limit of the GPU-addressable space. 311 * The IOMMU bit defines the upper limit of the GPU-addressable space.
312 * This will be refined in nouveau_ttm_init but we need to do it early
313 * for instmem to behave properly
314 */ 312 */
315 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(tdev->func->iommu_bit)); 313 ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(tdev->func->iommu_bit));
316 if (ret) 314 if (ret)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 513ee6b79553..17adcb4e8854 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -206,10 +206,12 @@ nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data)
206} 206}
207 207
208static int 208static int
209nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size) 209nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc,
210 enum nvkm_object_map *type, u64 *addr, u64 *size)
210{ 211{
211 struct nvkm_udevice *udev = nvkm_udevice(object); 212 struct nvkm_udevice *udev = nvkm_udevice(object);
212 struct nvkm_device *device = udev->device; 213 struct nvkm_device *device = udev->device;
214 *type = NVKM_OBJECT_MAP_IO;
213 *addr = device->func->resource_addr(device, 0); 215 *addr = device->func->resource_addr(device, 0);
214 *size = device->func->resource_size(device, 0); 216 *size = device->func->resource_size(device, 0);
215 return 0; 217 return 0;
@@ -292,6 +294,11 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index,
292 if (!sclass) { 294 if (!sclass) {
293 switch (index) { 295 switch (index) {
294 case 0: sclass = &nvkm_control_oclass; break; 296 case 0: sclass = &nvkm_control_oclass; break;
297 case 1:
298 if (!device->mmu)
299 return -EINVAL;
300 sclass = &device->mmu->user;
301 break;
295 default: 302 default:
296 return -EINVAL; 303 return -EINVAL;
297 } 304 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
index 0c0310498afd..723dcbde2ac2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
@@ -191,11 +191,13 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
191} 191}
192 192
193static int 193static int
194nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) 194nv50_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc,
195 enum nvkm_object_map *type, u64 *addr, u64 *size)
195{ 196{
196 struct nv50_disp_chan *chan = nv50_disp_chan(object); 197 struct nv50_disp_chan *chan = nv50_disp_chan(object);
197 struct nv50_disp *disp = chan->root->disp; 198 struct nv50_disp *disp = chan->root->disp;
198 struct nvkm_device *device = disp->base.engine.subdev.device; 199 struct nvkm_device *device = disp->base.engine.subdev.device;
200 *type = NVKM_OBJECT_MAP_IO;
199 *addr = device->func->resource_addr(device, 0) + 201 *addr = device->func->resource_addr(device, 0) +
200 0x640000 + (chan->chid.user * 0x1000); 202 0x640000 + (chan->chid.user * 0x1000);
201 *size = 0x001000; 203 *size = 0x001000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
index 737b38f6fbd2..9bb4ad5b0e57 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
@@ -1,6 +1,7 @@
1#ifndef __NV50_DISP_CHAN_H__ 1#ifndef __NV50_DISP_CHAN_H__
2#define __NV50_DISP_CHAN_H__ 2#define __NV50_DISP_CHAN_H__
3#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) 3#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object)
4#include <core/object.h>
4#include "nv50.h" 5#include "nv50.h"
5 6
6struct nv50_disp_chan { 7struct nv50_disp_chan {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index a1e8bf48b778..c9e0a8f7b5d5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -147,7 +147,7 @@ void gf119_hda_eld(struct nvkm_ior *, u8 *, u8);
147 147
148#define IOR_MSG(i,l,f,a...) do { \ 148#define IOR_MSG(i,l,f,a...) do { \
149 struct nvkm_ior *_ior = (i); \ 149 struct nvkm_ior *_ior = (i); \
150 nvkm_##l(&_ior->disp->engine.subdev, "%s: "f, _ior->name, ##a); \ 150 nvkm_##l(&_ior->disp->engine.subdev, "%s: "f"\n", _ior->name, ##a); \
151} while(0) 151} while(0)
152#define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a) 152#define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a)
153#define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a) 153#define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c
index c95942ef8216..49ef7e57aad4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c
@@ -26,7 +26,7 @@
26 26
27#include <core/gpuobj.h> 27#include <core/gpuobj.h>
28#include <subdev/fb.h> 28#include <subdev/fb.h>
29#include <subdev/mmu/nv04.h> 29#include <subdev/mmu/vmm.h>
30 30
31#include <nvif/class.h> 31#include <nvif/class.h>
32 32
@@ -49,8 +49,8 @@ nv04_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent,
49 int ret; 49 int ret;
50 50
51 if (dmaobj->clone) { 51 if (dmaobj->clone) {
52 struct nv04_mmu *mmu = nv04_mmu(device->mmu); 52 struct nvkm_memory *pgt =
53 struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0]; 53 device->mmu->vmm->pd->pt[0]->memory;
54 if (!dmaobj->base.start) 54 if (!dmaobj->base.start)
55 return nvkm_gpuobj_wrap(pgt, pgpuobj); 55 return nvkm_gpuobj_wrap(pgt, pgpuobj);
56 nvkm_kmap(pgt); 56 nvkm_kmap(pgt);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
index 2e7b4e2105ef..816ccaedfc73 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
@@ -99,7 +99,7 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
99 const u32 base = falcon->addr; 99 const u32 base = falcon->addr;
100 100
101 if (!suspend) { 101 if (!suspend) {
102 nvkm_memory_del(&falcon->core); 102 nvkm_memory_unref(&falcon->core);
103 if (falcon->external) { 103 if (falcon->external) {
104 vfree(falcon->data.data); 104 vfree(falcon->data.data);
105 vfree(falcon->code.data); 105 vfree(falcon->code.data);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
index 660ca7aa95ea..64f6b7654a08 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
@@ -27,6 +27,7 @@
27#include <core/client.h> 27#include <core/client.h>
28#include <core/gpuobj.h> 28#include <core/gpuobj.h>
29#include <core/notify.h> 29#include <core/notify.h>
30#include <subdev/mc.h>
30 31
31#include <nvif/event.h> 32#include <nvif/event.h>
32#include <nvif/unpack.h> 33#include <nvif/unpack.h>
@@ -278,6 +279,12 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine)
278 return 0; 279 return 0;
279} 280}
280 281
282static void
283nvkm_fifo_preinit(struct nvkm_engine *engine)
284{
285 nvkm_mc_reset(engine->subdev.device, NVKM_ENGINE_FIFO);
286}
287
281static int 288static int
282nvkm_fifo_init(struct nvkm_engine *engine) 289nvkm_fifo_init(struct nvkm_engine *engine)
283{ 290{
@@ -302,6 +309,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine)
302static const struct nvkm_engine_func 309static const struct nvkm_engine_func
303nvkm_fifo = { 310nvkm_fifo = {
304 .dtor = nvkm_fifo_dtor, 311 .dtor = nvkm_fifo_dtor,
312 .preinit = nvkm_fifo_preinit,
305 .oneinit = nvkm_fifo_oneinit, 313 .oneinit = nvkm_fifo_oneinit,
306 .init = nvkm_fifo_init, 314 .init = nvkm_fifo_init,
307 .fini = nvkm_fifo_fini, 315 .fini = nvkm_fifo_fini,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index fab760ae922f..d83485385934 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -117,8 +117,8 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
117 if (chan->func->engine_dtor) 117 if (chan->func->engine_dtor)
118 chan->func->engine_dtor(chan, engine); 118 chan->func->engine_dtor(chan, engine);
119 nvkm_object_del(&engn->object); 119 nvkm_object_del(&engn->object);
120 if (chan->vm) 120 if (chan->vmm)
121 atomic_dec(&chan->vm->engref[engine->subdev.index]); 121 atomic_dec(&chan->vmm->engref[engine->subdev.index]);
122 } 122 }
123} 123}
124 124
@@ -151,8 +151,8 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
151 .engine = oclass->engine, 151 .engine = oclass->engine,
152 }; 152 };
153 153
154 if (chan->vm) 154 if (chan->vmm)
155 atomic_inc(&chan->vm->engref[engine->subdev.index]); 155 atomic_inc(&chan->vmm->engref[engine->subdev.index]);
156 156
157 if (engine->func->fifo.cclass) { 157 if (engine->func->fifo.cclass) {
158 ret = engine->func->fifo.cclass(chan, &cclass, 158 ret = engine->func->fifo.cclass(chan, &cclass,
@@ -253,9 +253,11 @@ nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type,
253} 253}
254 254
255static int 255static int
256nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) 256nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc,
257 enum nvkm_object_map *type, u64 *addr, u64 *size)
257{ 258{
258 struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); 259 struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
260 *type = NVKM_OBJECT_MAP_IO;
259 *addr = chan->addr; 261 *addr = chan->addr;
260 *size = chan->size; 262 *size = chan->size;
261 return 0; 263 return 0;
@@ -325,7 +327,10 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object)
325 if (chan->user) 327 if (chan->user)
326 iounmap(chan->user); 328 iounmap(chan->user);
327 329
328 nvkm_vm_ref(NULL, &chan->vm, NULL); 330 if (chan->vmm) {
331 nvkm_vmm_part(chan->vmm, chan->inst->memory);
332 nvkm_vmm_unref(&chan->vmm);
333 }
329 334
330 nvkm_gpuobj_del(&chan->push); 335 nvkm_gpuobj_del(&chan->push);
331 nvkm_gpuobj_del(&chan->inst); 336 nvkm_gpuobj_del(&chan->inst);
@@ -347,13 +352,12 @@ nvkm_fifo_chan_func = {
347int 352int
348nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, 353nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func,
349 struct nvkm_fifo *fifo, u32 size, u32 align, bool zero, 354 struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
350 u64 vm, u64 push, u64 engines, int bar, u32 base, u32 user, 355 u64 hvmm, u64 push, u64 engines, int bar, u32 base,
351 const struct nvkm_oclass *oclass, 356 u32 user, const struct nvkm_oclass *oclass,
352 struct nvkm_fifo_chan *chan) 357 struct nvkm_fifo_chan *chan)
353{ 358{
354 struct nvkm_client *client = oclass->client; 359 struct nvkm_client *client = oclass->client;
355 struct nvkm_device *device = fifo->engine.subdev.device; 360 struct nvkm_device *device = fifo->engine.subdev.device;
356 struct nvkm_mmu *mmu = device->mmu;
357 struct nvkm_dmaobj *dmaobj; 361 struct nvkm_dmaobj *dmaobj;
358 unsigned long flags; 362 unsigned long flags;
359 int ret; 363 int ret;
@@ -382,16 +386,19 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func,
382 } 386 }
383 387
384 /* channel address space */ 388 /* channel address space */
385 if (!vm && mmu) { 389 if (hvmm) {
386 if (!client->vm || client->vm->mmu == mmu) { 390 struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm);
387 ret = nvkm_vm_ref(client->vm, &chan->vm, NULL); 391 if (IS_ERR(vmm))
388 if (ret) 392 return PTR_ERR(vmm);
389 return ret; 393
390 } else { 394 if (vmm->mmu != device->mmu)
391 return -EINVAL; 395 return -EINVAL;
392 } 396
393 } else { 397 ret = nvkm_vmm_join(vmm, chan->inst->memory);
394 return -ENOENT; 398 if (ret)
399 return ret;
400
401 chan->vmm = nvkm_vmm_ref(vmm);
395 } 402 }
396 403
397 /* allocate channel id */ 404 /* allocate channel id */
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
index 61797c4dd07a..a5c998fe4485 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
@@ -229,15 +229,18 @@ g84_fifo_chan_func = {
229}; 229};
230 230
231int 231int
232g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, 232g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
233 const struct nvkm_oclass *oclass, 233 const struct nvkm_oclass *oclass,
234 struct nv50_fifo_chan *chan) 234 struct nv50_fifo_chan *chan)
235{ 235{
236 struct nvkm_device *device = fifo->base.engine.subdev.device; 236 struct nvkm_device *device = fifo->base.engine.subdev.device;
237 int ret; 237 int ret;
238 238
239 if (!vmm)
240 return -EINVAL;
241
239 ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base, 242 ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
240 0x10000, 0x1000, false, vm, push, 243 0x10000, 0x1000, false, vmm, push,
241 (1ULL << NVKM_ENGINE_BSP) | 244 (1ULL << NVKM_ENGINE_BSP) |
242 (1ULL << NVKM_ENGINE_CE0) | 245 (1ULL << NVKM_ENGINE_CE0) |
243 (1ULL << NVKM_ENGINE_CIPHER) | 246 (1ULL << NVKM_ENGINE_CIPHER) |
@@ -277,9 +280,5 @@ g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
277 if (ret) 280 if (ret)
278 return ret; 281 return ret;
279 282
280 ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); 283 return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
281 if (ret)
282 return ret;
283
284 return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
285} 284}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
index 7d697e2dce1a..fc1142af02cf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
@@ -11,12 +11,9 @@ struct gf100_fifo_chan {
11 struct list_head head; 11 struct list_head head;
12 bool killed; 12 bool killed;
13 13
14 struct nvkm_gpuobj *pgd;
15 struct nvkm_vm *vm;
16
17 struct { 14 struct {
18 struct nvkm_gpuobj *inst; 15 struct nvkm_gpuobj *inst;
19 struct nvkm_vma vma; 16 struct nvkm_vma *vma;
20 } engn[NVKM_SUBDEV_NR]; 17 } engn[NVKM_SUBDEV_NR];
21}; 18};
22 19
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
index 230f64e5f731..5beb5c628473 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
@@ -12,12 +12,9 @@ struct gk104_fifo_chan {
12 struct list_head head; 12 struct list_head head;
13 bool killed; 13 bool killed;
14 14
15 struct nvkm_gpuobj *pgd;
16 struct nvkm_vm *vm;
17
18 struct { 15 struct {
19 struct nvkm_gpuobj *inst; 16 struct nvkm_gpuobj *inst;
20 struct nvkm_vma vma; 17 struct nvkm_vma *vma;
21 } engn[NVKM_SUBDEV_NR]; 18 } engn[NVKM_SUBDEV_NR];
22}; 19};
23 20
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
index 25b60aff40e4..85f7dbf53c99 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
@@ -206,7 +206,6 @@ void *
206nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) 206nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base)
207{ 207{
208 struct nv50_fifo_chan *chan = nv50_fifo_chan(base); 208 struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
209 nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
210 nvkm_ramht_del(&chan->ramht); 209 nvkm_ramht_del(&chan->ramht);
211 nvkm_gpuobj_del(&chan->pgd); 210 nvkm_gpuobj_del(&chan->pgd);
212 nvkm_gpuobj_del(&chan->eng); 211 nvkm_gpuobj_del(&chan->eng);
@@ -229,15 +228,18 @@ nv50_fifo_chan_func = {
229}; 228};
230 229
231int 230int
232nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, 231nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
233 const struct nvkm_oclass *oclass, 232 const struct nvkm_oclass *oclass,
234 struct nv50_fifo_chan *chan) 233 struct nv50_fifo_chan *chan)
235{ 234{
236 struct nvkm_device *device = fifo->base.engine.subdev.device; 235 struct nvkm_device *device = fifo->base.engine.subdev.device;
237 int ret; 236 int ret;
238 237
238 if (!vmm)
239 return -EINVAL;
240
239 ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base, 241 ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base,
240 0x10000, 0x1000, false, vm, push, 242 0x10000, 0x1000, false, vmm, push,
241 (1ULL << NVKM_ENGINE_DMAOBJ) | 243 (1ULL << NVKM_ENGINE_DMAOBJ) |
242 (1ULL << NVKM_ENGINE_SW) | 244 (1ULL << NVKM_ENGINE_SW) |
243 (1ULL << NVKM_ENGINE_GR) | 245 (1ULL << NVKM_ENGINE_GR) |
@@ -262,9 +264,5 @@ nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
262 if (ret) 264 if (ret)
263 return ret; 265 return ret;
264 266
265 ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); 267 return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
266 if (ret)
267 return ret;
268
269 return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
270} 268}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
index 4b9da469b704..d853056e040b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
@@ -13,19 +13,18 @@ struct nv50_fifo_chan {
13 struct nvkm_gpuobj *eng; 13 struct nvkm_gpuobj *eng;
14 struct nvkm_gpuobj *pgd; 14 struct nvkm_gpuobj *pgd;
15 struct nvkm_ramht *ramht; 15 struct nvkm_ramht *ramht;
16 struct nvkm_vm *vm;
17 16
18 struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR]; 17 struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR];
19}; 18};
20 19
21int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, 20int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
22 const struct nvkm_oclass *, struct nv50_fifo_chan *); 21 const struct nvkm_oclass *, struct nv50_fifo_chan *);
23void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); 22void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
24void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); 23void nv50_fifo_chan_fini(struct nvkm_fifo_chan *);
25void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); 24void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *);
26void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); 25void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
27 26
28int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, 27int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
29 const struct nvkm_oclass *, struct nv50_fifo_chan *); 28 const struct nvkm_oclass *, struct nv50_fifo_chan *);
30 29
31extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass; 30extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
index caa914074752..fc34cddcd2f5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
@@ -44,9 +44,9 @@ g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
44 44
45 nvif_ioctl(parent, "create channel dma size %d\n", size); 45 nvif_ioctl(parent, "create channel dma size %d\n", size);
46 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 46 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
47 nvif_ioctl(parent, "create channel dma vers %d vm %llx " 47 nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
48 "pushbuf %llx offset %016llx\n", 48 "pushbuf %llx offset %016llx\n",
49 args->v0.version, args->v0.vm, args->v0.pushbuf, 49 args->v0.version, args->v0.vmm, args->v0.pushbuf,
50 args->v0.offset); 50 args->v0.offset);
51 if (!args->v0.pushbuf) 51 if (!args->v0.pushbuf)
52 return -EINVAL; 52 return -EINVAL;
@@ -57,7 +57,7 @@ g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
57 return -ENOMEM; 57 return -ENOMEM;
58 *pobject = &chan->base.object; 58 *pobject = &chan->base.object;
59 59
60 ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, 60 ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
61 oclass, chan); 61 oclass, chan);
62 if (ret) 62 if (ret)
63 return ret; 63 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
index 0a7b6ed5ed28..c213122cf088 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
@@ -95,6 +95,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base)
95 nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); 95 nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0);
96 96
97 c = fifo->ramfc; 97 c = fifo->ramfc;
98 nvkm_kmap(fctx);
98 do { 99 do {
99 u32 rm = ((1ULL << c->bits) - 1) << c->regs; 100 u32 rm = ((1ULL << c->bits) - 1) << c->regs;
100 u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; 101 u32 cm = ((1ULL << c->bits) - 1) << c->ctxs;
@@ -102,6 +103,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base)
102 u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm); 103 u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm);
103 nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); 104 nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs));
104 } while ((++c)->bits); 105 } while ((++c)->bits);
106 nvkm_done(fctx);
105 107
106 c = fifo->ramfc; 108 c = fifo->ramfc;
107 do { 109 do {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
index 480bc3777be5..8043718ad150 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
@@ -44,9 +44,9 @@ nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
44 44
45 nvif_ioctl(parent, "create channel dma size %d\n", size); 45 nvif_ioctl(parent, "create channel dma size %d\n", size);
46 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 46 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
47 nvif_ioctl(parent, "create channel dma vers %d vm %llx " 47 nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
48 "pushbuf %llx offset %016llx\n", 48 "pushbuf %llx offset %016llx\n",
49 args->v0.version, args->v0.vm, args->v0.pushbuf, 49 args->v0.version, args->v0.vmm, args->v0.pushbuf,
50 args->v0.offset); 50 args->v0.offset);
51 if (!args->v0.pushbuf) 51 if (!args->v0.pushbuf)
52 return -EINVAL; 52 return -EINVAL;
@@ -57,7 +57,7 @@ nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
57 return -ENOMEM; 57 return -ENOMEM;
58 *pobject = &chan->base.object; 58 *pobject = &chan->base.object;
59 59
60 ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, 60 ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
61 oclass, chan); 61 oclass, chan);
62 if (ret) 62 if (ret)
63 return ret; 63 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index cd468ab1db12..f69576868164 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -559,6 +559,7 @@ gf100_fifo_oneinit(struct nvkm_fifo *base)
559 struct gf100_fifo *fifo = gf100_fifo(base); 559 struct gf100_fifo *fifo = gf100_fifo(base);
560 struct nvkm_subdev *subdev = &fifo->base.engine.subdev; 560 struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
561 struct nvkm_device *device = subdev->device; 561 struct nvkm_device *device = subdev->device;
562 struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
562 int ret; 563 int ret;
563 564
564 /* Determine number of PBDMAs by checking valid enable bits. */ 565 /* Determine number of PBDMAs by checking valid enable bits. */
@@ -584,12 +585,12 @@ gf100_fifo_oneinit(struct nvkm_fifo *base)
584 if (ret) 585 if (ret)
585 return ret; 586 return ret;
586 587
587 ret = nvkm_bar_umap(device->bar, 128 * 0x1000, 12, &fifo->user.bar); 588 ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem),
589 &fifo->user.bar);
588 if (ret) 590 if (ret)
589 return ret; 591 return ret;
590 592
591 nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); 593 return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0);
592 return 0;
593} 594}
594 595
595static void 596static void
@@ -628,7 +629,7 @@ gf100_fifo_init(struct nvkm_fifo *base)
628 } 629 }
629 630
630 nvkm_mask(device, 0x002200, 0x00000001, 0x00000001); 631 nvkm_mask(device, 0x002200, 0x00000001, 0x00000001);
631 nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); 632 nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
632 633
633 nvkm_wr32(device, 0x002100, 0xffffffff); 634 nvkm_wr32(device, 0x002100, 0xffffffff);
634 nvkm_wr32(device, 0x002140, 0x7fffffff); 635 nvkm_wr32(device, 0x002140, 0x7fffffff);
@@ -639,10 +640,11 @@ static void *
639gf100_fifo_dtor(struct nvkm_fifo *base) 640gf100_fifo_dtor(struct nvkm_fifo *base)
640{ 641{
641 struct gf100_fifo *fifo = gf100_fifo(base); 642 struct gf100_fifo *fifo = gf100_fifo(base);
642 nvkm_vm_put(&fifo->user.bar); 643 struct nvkm_device *device = fifo->base.engine.subdev.device;
643 nvkm_memory_del(&fifo->user.mem); 644 nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar);
644 nvkm_memory_del(&fifo->runlist.mem[0]); 645 nvkm_memory_unref(&fifo->user.mem);
645 nvkm_memory_del(&fifo->runlist.mem[1]); 646 nvkm_memory_unref(&fifo->runlist.mem[0]);
647 nvkm_memory_unref(&fifo->runlist.mem[1]);
646 return fifo; 648 return fifo;
647} 649}
648 650
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
index 70db58eab9c3..b81a2ad48aa4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
@@ -26,7 +26,7 @@ struct gf100_fifo {
26 26
27 struct { 27 struct {
28 struct nvkm_memory *mem; 28 struct nvkm_memory *mem;
29 struct nvkm_vma bar; 29 struct nvkm_vma *bar;
30 } user; 30 } user;
31}; 31};
32 32
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index a7e55c422501..84bd703dd897 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -771,6 +771,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
771 struct gk104_fifo *fifo = gk104_fifo(base); 771 struct gk104_fifo *fifo = gk104_fifo(base);
772 struct nvkm_subdev *subdev = &fifo->base.engine.subdev; 772 struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
773 struct nvkm_device *device = subdev->device; 773 struct nvkm_device *device = subdev->device;
774 struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
774 int engn, runl, pbid, ret, i, j; 775 int engn, runl, pbid, ret, i, j;
775 enum nvkm_devidx engidx; 776 enum nvkm_devidx engidx;
776 u32 *map; 777 u32 *map;
@@ -834,13 +835,12 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
834 if (ret) 835 if (ret)
835 return ret; 836 return ret;
836 837
837 ret = nvkm_bar_umap(device->bar, fifo->base.nr * 0x200, 12, 838 ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem),
838 &fifo->user.bar); 839 &fifo->user.bar);
839 if (ret) 840 if (ret)
840 return ret; 841 return ret;
841 842
842 nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); 843 return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0);
843 return 0;
844} 844}
845 845
846static void 846static void
@@ -866,7 +866,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
866 nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ 866 nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */
867 } 867 }
868 868
869 nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); 869 nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
870 870
871 nvkm_wr32(device, 0x002100, 0xffffffff); 871 nvkm_wr32(device, 0x002100, 0xffffffff);
872 nvkm_wr32(device, 0x002140, 0x7fffffff); 872 nvkm_wr32(device, 0x002140, 0x7fffffff);
@@ -876,14 +876,15 @@ static void *
876gk104_fifo_dtor(struct nvkm_fifo *base) 876gk104_fifo_dtor(struct nvkm_fifo *base)
877{ 877{
878 struct gk104_fifo *fifo = gk104_fifo(base); 878 struct gk104_fifo *fifo = gk104_fifo(base);
879 struct nvkm_device *device = fifo->base.engine.subdev.device;
879 int i; 880 int i;
880 881
881 nvkm_vm_put(&fifo->user.bar); 882 nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar);
882 nvkm_memory_del(&fifo->user.mem); 883 nvkm_memory_unref(&fifo->user.mem);
883 884
884 for (i = 0; i < fifo->runlist_nr; i++) { 885 for (i = 0; i < fifo->runlist_nr; i++) {
885 nvkm_memory_del(&fifo->runlist[i].mem[1]); 886 nvkm_memory_unref(&fifo->runlist[i].mem[1]);
886 nvkm_memory_del(&fifo->runlist[i].mem[0]); 887 nvkm_memory_unref(&fifo->runlist[i].mem[0]);
887 } 888 }
888 889
889 return fifo; 890 return fifo;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
index 44bff98d6725..466f1051f91a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
@@ -37,7 +37,7 @@ struct gk104_fifo {
37 37
38 struct { 38 struct {
39 struct nvkm_memory *mem; 39 struct nvkm_memory *mem;
40 struct nvkm_vma bar; 40 struct nvkm_vma *bar;
41 } user; 41 } user;
42}; 42};
43 43
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
index 77c2f2a28bf3..2121f517b1dd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
@@ -45,10 +45,10 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
45 45
46 nvif_ioctl(parent, "create channel gpfifo size %d\n", size); 46 nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
47 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 47 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
48 nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " 48 nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
49 "pushbuf %llx ioffset %016llx " 49 "pushbuf %llx ioffset %016llx "
50 "ilength %08x\n", 50 "ilength %08x\n",
51 args->v0.version, args->v0.vm, args->v0.pushbuf, 51 args->v0.version, args->v0.vmm, args->v0.pushbuf,
52 args->v0.ioffset, args->v0.ilength); 52 args->v0.ioffset, args->v0.ilength);
53 if (!args->v0.pushbuf) 53 if (!args->v0.pushbuf)
54 return -EINVAL; 54 return -EINVAL;
@@ -59,7 +59,7 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
59 return -ENOMEM; 59 return -ENOMEM;
60 *pobject = &chan->base.object; 60 *pobject = &chan->base.object;
61 61
62 ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, 62 ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
63 oclass, chan); 63 oclass, chan);
64 if (ret) 64 if (ret)
65 return ret; 65 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
index f9e0377d3d24..75f9632789b3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
@@ -111,7 +111,7 @@ gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
111 struct nvkm_gpuobj *inst = chan->base.inst; 111 struct nvkm_gpuobj *inst = chan->base.inst;
112 112
113 if (offset) { 113 if (offset) {
114 u64 addr = chan->engn[engine->subdev.index].vma.offset; 114 u64 addr = chan->engn[engine->subdev.index].vma->addr;
115 nvkm_kmap(inst); 115 nvkm_kmap(inst);
116 nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4); 116 nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
117 nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr)); 117 nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
@@ -126,7 +126,7 @@ gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
126 struct nvkm_engine *engine) 126 struct nvkm_engine *engine)
127{ 127{
128 struct gf100_fifo_chan *chan = gf100_fifo_chan(base); 128 struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
129 nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); 129 nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma);
130 nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); 130 nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
131} 131}
132 132
@@ -146,8 +146,13 @@ gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
146 if (ret) 146 if (ret)
147 return ret; 147 return ret;
148 148
149 return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, 149 ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size,
150 NV_MEM_ACCESS_RW, &chan->engn[engn].vma); 150 &chan->engn[engn].vma);
151 if (ret)
152 return ret;
153
154 return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm,
155 chan->engn[engn].vma, NULL, 0);
151} 156}
152 157
153static void 158static void
@@ -190,10 +195,7 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
190static void * 195static void *
191gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) 196gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
192{ 197{
193 struct gf100_fifo_chan *chan = gf100_fifo_chan(base); 198 return gf100_fifo_chan(base);
194 nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
195 nvkm_gpuobj_del(&chan->pgd);
196 return chan;
197} 199}
198 200
199static const struct nvkm_fifo_chan_func 201static const struct nvkm_fifo_chan_func
@@ -216,7 +218,6 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
216 struct fermi_channel_gpfifo_v0 v0; 218 struct fermi_channel_gpfifo_v0 v0;
217 } *args = data; 219 } *args = data;
218 struct gf100_fifo *fifo = gf100_fifo(base); 220 struct gf100_fifo *fifo = gf100_fifo(base);
219 struct nvkm_device *device = fifo->base.engine.subdev.device;
220 struct nvkm_object *parent = oclass->parent; 221 struct nvkm_object *parent = oclass->parent;
221 struct gf100_fifo_chan *chan; 222 struct gf100_fifo_chan *chan;
222 u64 usermem, ioffset, ilength; 223 u64 usermem, ioffset, ilength;
@@ -224,10 +225,12 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
224 225
225 nvif_ioctl(parent, "create channel gpfifo size %d\n", size); 226 nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
226 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 227 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
227 nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " 228 nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
228 "ioffset %016llx ilength %08x\n", 229 "ioffset %016llx ilength %08x\n",
229 args->v0.version, args->v0.vm, args->v0.ioffset, 230 args->v0.version, args->v0.vmm, args->v0.ioffset,
230 args->v0.ilength); 231 args->v0.ilength);
232 if (!args->v0.vmm)
233 return -EINVAL;
231 } else 234 } else
232 return ret; 235 return ret;
233 236
@@ -239,7 +242,7 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
239 INIT_LIST_HEAD(&chan->head); 242 INIT_LIST_HEAD(&chan->head);
240 243
241 ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, 244 ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base,
242 0x1000, 0x1000, true, args->v0.vm, 0, 245 0x1000, 0x1000, true, args->v0.vmm, 0,
243 (1ULL << NVKM_ENGINE_CE0) | 246 (1ULL << NVKM_ENGINE_CE0) |
244 (1ULL << NVKM_ENGINE_CE1) | 247 (1ULL << NVKM_ENGINE_CE1) |
245 (1ULL << NVKM_ENGINE_GR) | 248 (1ULL << NVKM_ENGINE_GR) |
@@ -247,29 +250,13 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
247 (1ULL << NVKM_ENGINE_MSPPP) | 250 (1ULL << NVKM_ENGINE_MSPPP) |
248 (1ULL << NVKM_ENGINE_MSVLD) | 251 (1ULL << NVKM_ENGINE_MSVLD) |
249 (1ULL << NVKM_ENGINE_SW), 252 (1ULL << NVKM_ENGINE_SW),
250 1, fifo->user.bar.offset, 0x1000, 253 1, fifo->user.bar->addr, 0x1000,
251 oclass, &chan->base); 254 oclass, &chan->base);
252 if (ret) 255 if (ret)
253 return ret; 256 return ret;
254 257
255 args->v0.chid = chan->base.chid; 258 args->v0.chid = chan->base.chid;
256 259
257 /* page directory */
258 ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
259 if (ret)
260 return ret;
261
262 nvkm_kmap(chan->base.inst);
263 nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
264 nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
265 nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
266 nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
267 nvkm_done(chan->base.inst);
268
269 ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
270 if (ret)
271 return ret;
272
273 /* clear channel control registers */ 260 /* clear channel control registers */
274 261
275 usermem = chan->base.chid * 0x1000; 262 usermem = chan->base.chid * 0x1000;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
index 8abf6f8ef445..80c87521bebe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
@@ -117,7 +117,7 @@ gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
117 u32 offset = gk104_fifo_gpfifo_engine_addr(engine); 117 u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
118 118
119 if (offset) { 119 if (offset) {
120 u64 addr = chan->engn[engine->subdev.index].vma.offset; 120 u64 addr = chan->engn[engine->subdev.index].vma->addr;
121 u32 datalo = lower_32_bits(addr) | 0x00000004; 121 u32 datalo = lower_32_bits(addr) | 0x00000004;
122 u32 datahi = upper_32_bits(addr); 122 u32 datahi = upper_32_bits(addr);
123 nvkm_kmap(inst); 123 nvkm_kmap(inst);
@@ -138,7 +138,7 @@ gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
138 struct nvkm_engine *engine) 138 struct nvkm_engine *engine)
139{ 139{
140 struct gk104_fifo_chan *chan = gk104_fifo_chan(base); 140 struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
141 nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); 141 nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma);
142 nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); 142 nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
143} 143}
144 144
@@ -158,8 +158,13 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
158 if (ret) 158 if (ret)
159 return ret; 159 return ret;
160 160
161 return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, 161 ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size,
162 NV_MEM_ACCESS_RW, &chan->engn[engn].vma); 162 &chan->engn[engn].vma);
163 if (ret)
164 return ret;
165
166 return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm,
167 chan->engn[engn].vma, NULL, 0);
163} 168}
164 169
165static void 170static void
@@ -203,10 +208,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
203static void * 208static void *
204gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) 209gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
205{ 210{
206 struct gk104_fifo_chan *chan = gk104_fifo_chan(base); 211 return gk104_fifo_chan(base);
207 nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
208 nvkm_gpuobj_del(&chan->pgd);
209 return chan;
210} 212}
211 213
212static const struct nvkm_fifo_chan_func 214static const struct nvkm_fifo_chan_func
@@ -229,17 +231,19 @@ struct gk104_fifo_chan_func {
229static int 231static int
230gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, 232gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func,
231 struct gk104_fifo *fifo, u32 *engmask, u16 *chid, 233 struct gk104_fifo *fifo, u32 *engmask, u16 *chid,
232 u64 vm, u64 ioffset, u64 ilength, 234 u64 vmm, u64 ioffset, u64 ilength,
233 const struct nvkm_oclass *oclass, 235 const struct nvkm_oclass *oclass,
234 struct nvkm_object **pobject) 236 struct nvkm_object **pobject)
235{ 237{
236 struct nvkm_device *device = fifo->base.engine.subdev.device;
237 struct gk104_fifo_chan *chan; 238 struct gk104_fifo_chan *chan;
238 int runlist = -1, ret = -ENOSYS, i, j; 239 int runlist = -1, ret = -ENOSYS, i, j;
239 u32 engines = 0, present = 0; 240 u32 engines = 0, present = 0;
240 u64 subdevs = 0; 241 u64 subdevs = 0;
241 u64 usermem; 242 u64 usermem;
242 243
244 if (!vmm)
245 return -EINVAL;
246
243 /* Determine which downstream engines are present */ 247 /* Determine which downstream engines are present */
244 for (i = 0; i < fifo->engine_nr; i++) { 248 for (i = 0; i < fifo->engine_nr; i++) {
245 struct nvkm_engine *engine = fifo->engine[i].engine; 249 struct nvkm_engine *engine = fifo->engine[i].engine;
@@ -285,30 +289,14 @@ gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func,
285 INIT_LIST_HEAD(&chan->head); 289 INIT_LIST_HEAD(&chan->head);
286 290
287 ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, 291 ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
288 0x1000, 0x1000, true, vm, 0, subdevs, 292 0x1000, 0x1000, true, vmm, 0, subdevs,
289 1, fifo->user.bar.offset, 0x200, 293 1, fifo->user.bar->addr, 0x200,
290 oclass, &chan->base); 294 oclass, &chan->base);
291 if (ret) 295 if (ret)
292 return ret; 296 return ret;
293 297
294 *chid = chan->base.chid; 298 *chid = chan->base.chid;
295 299
296 /* Page directory. */
297 ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
298 if (ret)
299 return ret;
300
301 nvkm_kmap(chan->base.inst);
302 nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
303 nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
304 nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
305 nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
306 nvkm_done(chan->base.inst);
307
308 ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
309 if (ret)
310 return ret;
311
312 /* Clear channel control registers. */ 300 /* Clear channel control registers. */
313 usermem = chan->base.chid * 0x200; 301 usermem = chan->base.chid * 0x200;
314 ilength = order_base_2(ilength / 8); 302 ilength = order_base_2(ilength / 8);
@@ -373,18 +361,17 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
373 361
374 nvif_ioctl(parent, "create channel gpfifo size %d\n", size); 362 nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
375 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 363 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
376 nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " 364 nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
377 "ioffset %016llx ilength %08x engine %08x\n", 365 "ioffset %016llx ilength %08x engine %08x\n",
378 args->v0.version, args->v0.vm, args->v0.ioffset, 366 args->v0.version, args->v0.vmm, args->v0.ioffset,
379 args->v0.ilength, args->v0.engines); 367 args->v0.ilength, args->v0.engines);
380 return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo, 368 return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo,
381 &args->v0.engines, 369 &args->v0.engines,
382 &args->v0.chid, 370 &args->v0.chid,
383 args->v0.vm, 371 args->v0.vmm,
384 args->v0.ioffset, 372 args->v0.ioffset,
385 args->v0.ilength, 373 args->v0.ilength,
386 oclass, pobject); 374 oclass, pobject);
387
388 } 375 }
389 376
390 return ret; 377 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
index c5a7de9db259..d8f28ec1e4a8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
@@ -45,10 +45,10 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
45 45
46 nvif_ioctl(parent, "create channel gpfifo size %d\n", size); 46 nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
47 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { 47 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
48 nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " 48 nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
49 "pushbuf %llx ioffset %016llx " 49 "pushbuf %llx ioffset %016llx "
50 "ilength %08x\n", 50 "ilength %08x\n",
51 args->v0.version, args->v0.vm, args->v0.pushbuf, 51 args->v0.version, args->v0.vmm, args->v0.pushbuf,
52 args->v0.ioffset, args->v0.ilength); 52 args->v0.ioffset, args->v0.ilength);
53 if (!args->v0.pushbuf) 53 if (!args->v0.pushbuf)
54 return -EINVAL; 54 return -EINVAL;
@@ -59,7 +59,7 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
59 return -ENOMEM; 59 return -ENOMEM;
60 *pobject = &chan->base.object; 60 *pobject = &chan->base.object;
61 61
62 ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, 62 ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
63 oclass, chan); 63 oclass, chan);
64 if (ret) 64 if (ret)
65 return ret; 65 return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
index 66eb12c2b5ba..fa6e094d8068 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
@@ -100,8 +100,8 @@ void *
100nv50_fifo_dtor(struct nvkm_fifo *base) 100nv50_fifo_dtor(struct nvkm_fifo *base)
101{ 101{
102 struct nv50_fifo *fifo = nv50_fifo(base); 102 struct nv50_fifo *fifo = nv50_fifo(base);
103 nvkm_memory_del(&fifo->runlist[1]); 103 nvkm_memory_unref(&fifo->runlist[1]);
104 nvkm_memory_del(&fifo->runlist[0]); 104 nvkm_memory_unref(&fifo->runlist[0]);
105 return fifo; 105 return fifo;
106} 106}
107 107
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
index bc77eea351a5..881015080d83 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
@@ -986,14 +986,14 @@ gf100_grctx_pack_tpc[] = {
986 ******************************************************************************/ 986 ******************************************************************************/
987 987
988int 988int
989gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, u32 access) 989gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, bool priv)
990{ 990{
991 if (info->data) { 991 if (info->data) {
992 info->buffer[info->buffer_nr] = round_up(info->addr, align); 992 info->buffer[info->buffer_nr] = round_up(info->addr, align);
993 info->addr = info->buffer[info->buffer_nr] + size; 993 info->addr = info->buffer[info->buffer_nr] + size;
994 info->data->size = size; 994 info->data->size = size;
995 info->data->align = align; 995 info->data->align = align;
996 info->data->access = access; 996 info->data->priv = priv;
997 info->data++; 997 info->data++;
998 return info->buffer_nr++; 998 return info->buffer_nr++;
999 } 999 }
@@ -1028,9 +1028,8 @@ void
1028gf100_grctx_generate_bundle(struct gf100_grctx *info) 1028gf100_grctx_generate_bundle(struct gf100_grctx *info)
1029{ 1029{
1030 const struct gf100_grctx_func *grctx = info->gr->func->grctx; 1030 const struct gf100_grctx_func *grctx = info->gr->func->grctx;
1031 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
1032 const int s = 8; 1031 const int s = 8;
1033 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); 1032 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
1034 mmio_refn(info, 0x408004, 0x00000000, s, b); 1033 mmio_refn(info, 0x408004, 0x00000000, s, b);
1035 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); 1034 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
1036 mmio_refn(info, 0x418808, 0x00000000, s, b); 1035 mmio_refn(info, 0x418808, 0x00000000, s, b);
@@ -1041,9 +1040,8 @@ void
1041gf100_grctx_generate_pagepool(struct gf100_grctx *info) 1040gf100_grctx_generate_pagepool(struct gf100_grctx *info)
1042{ 1041{
1043 const struct gf100_grctx_func *grctx = info->gr->func->grctx; 1042 const struct gf100_grctx_func *grctx = info->gr->func->grctx;
1044 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
1045 const int s = 8; 1043 const int s = 8;
1046 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); 1044 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
1047 mmio_refn(info, 0x40800c, 0x00000000, s, b); 1045 mmio_refn(info, 0x40800c, 0x00000000, s, b);
1048 mmio_wr32(info, 0x408010, 0x80000000); 1046 mmio_wr32(info, 0x408010, 0x80000000);
1049 mmio_refn(info, 0x419004, 0x00000000, s, b); 1047 mmio_refn(info, 0x419004, 0x00000000, s, b);
@@ -1057,9 +1055,8 @@ gf100_grctx_generate_attrib(struct gf100_grctx *info)
1057 const struct gf100_grctx_func *grctx = gr->func->grctx; 1055 const struct gf100_grctx_func *grctx = gr->func->grctx;
1058 const u32 attrib = grctx->attrib_nr; 1056 const u32 attrib = grctx->attrib_nr;
1059 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 1057 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
1060 const u32 access = NV_MEM_ACCESS_RW;
1061 const int s = 12; 1058 const int s = 12;
1062 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); 1059 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
1063 int gpc, tpc; 1060 int gpc, tpc;
1064 u32 bo = 0; 1061 u32 bo = 0;
1065 1062
@@ -1267,85 +1264,87 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
1267 nvkm_mc_unk260(device, 1); 1264 nvkm_mc_unk260(device, 1);
1268} 1265}
1269 1266
1267#define CB_RESERVED 0x80000
1268
1270int 1269int
1271gf100_grctx_generate(struct gf100_gr *gr) 1270gf100_grctx_generate(struct gf100_gr *gr)
1272{ 1271{
1273 const struct gf100_grctx_func *grctx = gr->func->grctx; 1272 const struct gf100_grctx_func *grctx = gr->func->grctx;
1274 struct nvkm_subdev *subdev = &gr->base.engine.subdev; 1273 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1275 struct nvkm_device *device = subdev->device; 1274 struct nvkm_device *device = subdev->device;
1276 struct nvkm_memory *chan; 1275 struct nvkm_memory *inst = NULL;
1276 struct nvkm_memory *data = NULL;
1277 struct nvkm_vmm *vmm = NULL;
1278 struct nvkm_vma *ctx = NULL;
1277 struct gf100_grctx info; 1279 struct gf100_grctx info;
1278 int ret, i; 1280 int ret, i;
1279 u64 addr; 1281 u64 addr;
1280 1282
1281 /* allocate memory to for a "channel", which we'll use to generate 1283 /* Allocate memory to for a "channel", which we'll use to generate
1282 * the default context values 1284 * the default context values.
1283 */ 1285 */
1284 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x80000 + gr->size, 1286 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
1285 0x1000, true, &chan); 1287 0x1000, 0x1000, true, &inst);
1286 if (ret) { 1288 if (ret)
1287 nvkm_error(subdev, "failed to allocate chan memory, %d\n", ret); 1289 goto done;
1288 return ret;
1289 }
1290 1290
1291 addr = nvkm_memory_addr(chan); 1291 ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "grctx", &vmm);
1292 if (ret)
1293 goto done;
1292 1294
1293 /* PGD pointer */ 1295 vmm->debug = subdev->debug;
1294 nvkm_kmap(chan);
1295 nvkm_wo32(chan, 0x0200, lower_32_bits(addr + 0x1000));
1296 nvkm_wo32(chan, 0x0204, upper_32_bits(addr + 0x1000));
1297 nvkm_wo32(chan, 0x0208, 0xffffffff);
1298 nvkm_wo32(chan, 0x020c, 0x000000ff);
1299 1296
1300 /* PGT[0] pointer */ 1297 ret = nvkm_vmm_join(vmm, inst);
1301 nvkm_wo32(chan, 0x1000, 0x00000000); 1298 if (ret)
1302 nvkm_wo32(chan, 0x1004, 0x00000001 | (addr + 0x2000) >> 8); 1299 goto done;
1303 1300
1304 /* identity-map the whole "channel" into its own vm */ 1301 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
1305 for (i = 0; i < nvkm_memory_size(chan) / 4096; i++) { 1302 CB_RESERVED + gr->size, 0, true, &data);
1306 u64 addr = ((nvkm_memory_addr(chan) + (i * 4096)) >> 8) | 1; 1303 if (ret)
1307 nvkm_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); 1304 goto done;
1308 nvkm_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr));
1309 }
1310 1305
1311 /* context pointer (virt) */ 1306 ret = nvkm_vmm_get(vmm, 0, nvkm_memory_size(data), &ctx);
1312 nvkm_wo32(chan, 0x0210, 0x00080004); 1307 if (ret)
1313 nvkm_wo32(chan, 0x0214, 0x00000000); 1308 goto done;
1314 nvkm_done(chan);
1315 1309
1316 nvkm_wr32(device, 0x100cb8, (addr + 0x1000) >> 8); 1310 ret = nvkm_memory_map(data, 0, vmm, ctx, NULL, 0);
1317 nvkm_wr32(device, 0x100cbc, 0x80000001); 1311 if (ret)
1318 nvkm_msec(device, 2000, 1312 goto done;
1319 if (nvkm_rd32(device, 0x100c80) & 0x00008000) 1313
1320 break; 1314
1321 ); 1315 /* Setup context pointer. */
1316 nvkm_kmap(inst);
1317 nvkm_wo32(inst, 0x0210, lower_32_bits(ctx->addr + CB_RESERVED) | 4);
1318 nvkm_wo32(inst, 0x0214, upper_32_bits(ctx->addr + CB_RESERVED));
1319 nvkm_done(inst);
1322 1320
1323 /* setup default state for mmio list construction */ 1321 /* Setup default state for mmio list construction. */
1324 info.gr = gr; 1322 info.gr = gr;
1325 info.data = gr->mmio_data; 1323 info.data = gr->mmio_data;
1326 info.mmio = gr->mmio_list; 1324 info.mmio = gr->mmio_list;
1327 info.addr = 0x2000 + (i * 8); 1325 info.addr = ctx->addr;
1328 info.buffer_nr = 0; 1326 info.buffer_nr = 0;
1329 1327
1330 /* make channel current */ 1328 /* Make channel current. */
1329 addr = nvkm_memory_addr(inst) >> 12;
1331 if (gr->firmware) { 1330 if (gr->firmware) {
1332 nvkm_wr32(device, 0x409840, 0x00000030); 1331 nvkm_wr32(device, 0x409840, 0x00000030);
1333 nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); 1332 nvkm_wr32(device, 0x409500, 0x80000000 | addr);
1334 nvkm_wr32(device, 0x409504, 0x00000003); 1333 nvkm_wr32(device, 0x409504, 0x00000003);
1335 nvkm_msec(device, 2000, 1334 nvkm_msec(device, 2000,
1336 if (nvkm_rd32(device, 0x409800) & 0x00000010) 1335 if (nvkm_rd32(device, 0x409800) & 0x00000010)
1337 break; 1336 break;
1338 ); 1337 );
1339 1338
1340 nvkm_kmap(chan); 1339 nvkm_kmap(data);
1341 nvkm_wo32(chan, 0x8001c, 1); 1340 nvkm_wo32(data, 0x1c, 1);
1342 nvkm_wo32(chan, 0x80020, 0); 1341 nvkm_wo32(data, 0x20, 0);
1343 nvkm_wo32(chan, 0x80028, 0); 1342 nvkm_wo32(data, 0x28, 0);
1344 nvkm_wo32(chan, 0x8002c, 0); 1343 nvkm_wo32(data, 0x2c, 0);
1345 nvkm_done(chan); 1344 nvkm_done(data);
1346 } else { 1345 } else {
1347 nvkm_wr32(device, 0x409840, 0x80000000); 1346 nvkm_wr32(device, 0x409840, 0x80000000);
1348 nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); 1347 nvkm_wr32(device, 0x409500, 0x80000000 | addr);
1349 nvkm_wr32(device, 0x409504, 0x00000001); 1348 nvkm_wr32(device, 0x409504, 0x00000001);
1350 nvkm_msec(device, 2000, 1349 nvkm_msec(device, 2000,
1351 if (nvkm_rd32(device, 0x409800) & 0x80000000) 1350 if (nvkm_rd32(device, 0x409800) & 0x80000000)
@@ -1355,8 +1354,8 @@ gf100_grctx_generate(struct gf100_gr *gr)
1355 1354
1356 grctx->main(gr, &info); 1355 grctx->main(gr, &info);
1357 1356
1358 /* trigger a context unload by unsetting the "next channel valid" bit 1357 /* Trigger a context unload by unsetting the "next channel valid" bit
1359 * and faking a context switch interrupt 1358 * and faking a context switch interrupt.
1360 */ 1359 */
1361 nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000); 1360 nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000);
1362 nvkm_wr32(device, 0x409000, 0x00000100); 1361 nvkm_wr32(device, 0x409000, 0x00000100);
@@ -1370,17 +1369,21 @@ gf100_grctx_generate(struct gf100_gr *gr)
1370 1369
1371 gr->data = kmalloc(gr->size, GFP_KERNEL); 1370 gr->data = kmalloc(gr->size, GFP_KERNEL);
1372 if (gr->data) { 1371 if (gr->data) {
1373 nvkm_kmap(chan); 1372 nvkm_kmap(data);
1374 for (i = 0; i < gr->size; i += 4) 1373 for (i = 0; i < gr->size; i += 4)
1375 gr->data[i / 4] = nvkm_ro32(chan, 0x80000 + i); 1374 gr->data[i / 4] = nvkm_ro32(data, CB_RESERVED + i);
1376 nvkm_done(chan); 1375 nvkm_done(data);
1377 ret = 0; 1376 ret = 0;
1378 } else { 1377 } else {
1379 ret = -ENOMEM; 1378 ret = -ENOMEM;
1380 } 1379 }
1381 1380
1382done: 1381done:
1383 nvkm_memory_del(&chan); 1382 nvkm_vmm_put(vmm, &ctx);
1383 nvkm_memory_unref(&data);
1384 nvkm_vmm_part(vmm, inst);
1385 nvkm_vmm_unref(&vmm);
1386 nvkm_memory_unref(&inst);
1384 return ret; 1387 return ret;
1385} 1388}
1386 1389
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
index 017180d147cf..4731e56fbb11 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
@@ -11,7 +11,7 @@ struct gf100_grctx {
11 u64 addr; 11 u64 addr;
12}; 12};
13 13
14int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, u32 access); 14int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv);
15void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int); 15void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int);
16 16
17#define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d)) 17#define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d))
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
index 505cdcbfc085..82f71b10c06e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
@@ -735,9 +735,8 @@ gf108_grctx_generate_attrib(struct gf100_grctx *info)
735 const u32 alpha = grctx->alpha_nr; 735 const u32 alpha = grctx->alpha_nr;
736 const u32 beta = grctx->attrib_nr; 736 const u32 beta = grctx->attrib_nr;
737 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 737 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
738 const u32 access = NV_MEM_ACCESS_RW;
739 const int s = 12; 738 const int s = 12;
740 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); 739 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
741 const int timeslice_mode = 1; 740 const int timeslice_mode = 1;
742 const int max_batches = 0xffff; 741 const int max_batches = 0xffff;
743 u32 bo = 0; 742 u32 bo = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
index 74a64e3fd59a..19301d88577d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
@@ -187,9 +187,8 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info)
187 const u32 alpha = grctx->alpha_nr; 187 const u32 alpha = grctx->alpha_nr;
188 const u32 beta = grctx->attrib_nr; 188 const u32 beta = grctx->attrib_nr;
189 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 189 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
190 const u32 access = NV_MEM_ACCESS_RW;
191 const int s = 12; 190 const int s = 12;
192 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); 191 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
193 const int timeslice_mode = 1; 192 const int timeslice_mode = 1;
194 const int max_batches = 0xffff; 193 const int max_batches = 0xffff;
195 u32 bo = 0; 194 u32 bo = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
index c46b3fdf7203..825c8fd500bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
@@ -847,9 +847,8 @@ gk104_grctx_generate_bundle(struct gf100_grctx *info)
847 const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, 847 const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth,
848 grctx->bundle_size / 0x20); 848 grctx->bundle_size / 0x20);
849 const u32 token_limit = grctx->bundle_token_limit; 849 const u32 token_limit = grctx->bundle_token_limit;
850 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
851 const int s = 8; 850 const int s = 8;
852 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); 851 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
853 mmio_refn(info, 0x408004, 0x00000000, s, b); 852 mmio_refn(info, 0x408004, 0x00000000, s, b);
854 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); 853 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
855 mmio_refn(info, 0x418808, 0x00000000, s, b); 854 mmio_refn(info, 0x418808, 0x00000000, s, b);
@@ -861,9 +860,8 @@ void
861gk104_grctx_generate_pagepool(struct gf100_grctx *info) 860gk104_grctx_generate_pagepool(struct gf100_grctx *info)
862{ 861{
863 const struct gf100_grctx_func *grctx = info->gr->func->grctx; 862 const struct gf100_grctx_func *grctx = info->gr->func->grctx;
864 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
865 const int s = 8; 863 const int s = 8;
866 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); 864 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
867 mmio_refn(info, 0x40800c, 0x00000000, s, b); 865 mmio_refn(info, 0x40800c, 0x00000000, s, b);
868 mmio_wr32(info, 0x408010, 0x80000000); 866 mmio_wr32(info, 0x408010, 0x80000000);
869 mmio_refn(info, 0x419004, 0x00000000, s, b); 867 mmio_refn(info, 0x419004, 0x00000000, s, b);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
index 4c4b5ab6e46d..9b43d4ce3eaa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
@@ -867,9 +867,8 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info)
867 const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, 867 const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth,
868 grctx->bundle_size / 0x20); 868 grctx->bundle_size / 0x20);
869 const u32 token_limit = grctx->bundle_token_limit; 869 const u32 token_limit = grctx->bundle_token_limit;
870 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
871 const int s = 8; 870 const int s = 8;
872 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); 871 const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
873 mmio_refn(info, 0x408004, 0x00000000, s, b); 872 mmio_refn(info, 0x408004, 0x00000000, s, b);
874 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); 873 mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
875 mmio_refn(info, 0x418e24, 0x00000000, s, b); 874 mmio_refn(info, 0x418e24, 0x00000000, s, b);
@@ -881,9 +880,8 @@ void
881gm107_grctx_generate_pagepool(struct gf100_grctx *info) 880gm107_grctx_generate_pagepool(struct gf100_grctx *info)
882{ 881{
883 const struct gf100_grctx_func *grctx = info->gr->func->grctx; 882 const struct gf100_grctx_func *grctx = info->gr->func->grctx;
884 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
885 const int s = 8; 883 const int s = 8;
886 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); 884 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
887 mmio_refn(info, 0x40800c, 0x00000000, s, b); 885 mmio_refn(info, 0x40800c, 0x00000000, s, b);
888 mmio_wr32(info, 0x408010, 0x80000000); 886 mmio_wr32(info, 0x408010, 0x80000000);
889 mmio_refn(info, 0x419004, 0x00000000, s, b); 887 mmio_refn(info, 0x419004, 0x00000000, s, b);
@@ -900,9 +898,8 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info)
900 const u32 alpha = grctx->alpha_nr; 898 const u32 alpha = grctx->alpha_nr;
901 const u32 attrib = grctx->attrib_nr; 899 const u32 attrib = grctx->attrib_nr;
902 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 900 const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
903 const u32 access = NV_MEM_ACCESS_RW;
904 const int s = 12; 901 const int s = 12;
905 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); 902 const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
906 const int max_batches = 0xffff; 903 const int max_batches = 0xffff;
907 u32 bo = 0; 904 u32 bo = 0;
908 u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; 905 u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
index 7833bc777a29..88ea322d956c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
@@ -33,9 +33,8 @@ void
33gp100_grctx_generate_pagepool(struct gf100_grctx *info) 33gp100_grctx_generate_pagepool(struct gf100_grctx *info)
34{ 34{
35 const struct gf100_grctx_func *grctx = info->gr->func->grctx; 35 const struct gf100_grctx_func *grctx = info->gr->func->grctx;
36 const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
37 const int s = 8; 36 const int s = 8;
38 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); 37 const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
39 mmio_refn(info, 0x40800c, 0x00000000, s, b); 38 mmio_refn(info, 0x40800c, 0x00000000, s, b);
40 mmio_wr32(info, 0x408010, 0x80000000); 39 mmio_wr32(info, 0x408010, 0x80000000);
41 mmio_refn(info, 0x419004, 0x00000000, s, b); 40 mmio_refn(info, 0x419004, 0x00000000, s, b);
@@ -51,9 +50,8 @@ gp100_grctx_generate_attrib(struct gf100_grctx *info)
51 const u32 attrib = grctx->attrib_nr; 50 const u32 attrib = grctx->attrib_nr;
52 const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 51 const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
53 const u32 size = roundup(gr->tpc_total * pertpc, 0x80); 52 const u32 size = roundup(gr->tpc_total * pertpc, 0x80);
54 const u32 access = NV_MEM_ACCESS_RW;
55 const int s = 12; 53 const int s = 12;
56 const int b = mmio_vram(info, size, (1 << s), access); 54 const int b = mmio_vram(info, size, (1 << s), false);
57 const int max_batches = 0xffff; 55 const int max_batches = 0xffff;
58 u32 ao = 0; 56 u32 ao = 0;
59 u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total; 57 u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
index 80b7ab0bee3a..7a66b4c2eb18 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
@@ -38,9 +38,8 @@ gp102_grctx_generate_attrib(struct gf100_grctx *info)
38 const u32 attrib = grctx->attrib_nr; 38 const u32 attrib = grctx->attrib_nr;
39 const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); 39 const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
40 const u32 size = roundup(gr->tpc_total * pertpc, 0x80); 40 const u32 size = roundup(gr->tpc_total * pertpc, 0x80);
41 const u32 access = NV_MEM_ACCESS_RW;
42 const int s = 12; 41 const int s = 12;
43 const int b = mmio_vram(info, size, (1 << s), access); 42 const int b = mmio_vram(info, size, (1 << s), false);
44 const int max_batches = 0xffff; 43 const int max_batches = 0xffff;
45 u32 ao = 0; 44 u32 ao = 0;
46 u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total; 45 u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 99689f4de502..2f8dc107047d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -37,6 +37,7 @@
37 37
38#include <nvif/class.h> 38#include <nvif/class.h>
39#include <nvif/cl9097.h> 39#include <nvif/cl9097.h>
40#include <nvif/if900d.h>
40#include <nvif/unpack.h> 41#include <nvif/unpack.h>
41 42
42/******************************************************************************* 43/*******************************************************************************
@@ -327,13 +328,13 @@ gf100_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
327 328
328 if (!gr->firmware) { 329 if (!gr->firmware) {
329 nvkm_wo32(*pgpuobj, 0x00, chan->mmio_nr / 2); 330 nvkm_wo32(*pgpuobj, 0x00, chan->mmio_nr / 2);
330 nvkm_wo32(*pgpuobj, 0x04, chan->mmio_vma.offset >> 8); 331 nvkm_wo32(*pgpuobj, 0x04, chan->mmio_vma->addr >> 8);
331 } else { 332 } else {
332 nvkm_wo32(*pgpuobj, 0xf4, 0); 333 nvkm_wo32(*pgpuobj, 0xf4, 0);
333 nvkm_wo32(*pgpuobj, 0xf8, 0); 334 nvkm_wo32(*pgpuobj, 0xf8, 0);
334 nvkm_wo32(*pgpuobj, 0x10, chan->mmio_nr / 2); 335 nvkm_wo32(*pgpuobj, 0x10, chan->mmio_nr / 2);
335 nvkm_wo32(*pgpuobj, 0x14, lower_32_bits(chan->mmio_vma.offset)); 336 nvkm_wo32(*pgpuobj, 0x14, lower_32_bits(chan->mmio_vma->addr));
336 nvkm_wo32(*pgpuobj, 0x18, upper_32_bits(chan->mmio_vma.offset)); 337 nvkm_wo32(*pgpuobj, 0x18, upper_32_bits(chan->mmio_vma->addr));
337 nvkm_wo32(*pgpuobj, 0x1c, 1); 338 nvkm_wo32(*pgpuobj, 0x1c, 1);
338 nvkm_wo32(*pgpuobj, 0x20, 0); 339 nvkm_wo32(*pgpuobj, 0x20, 0);
339 nvkm_wo32(*pgpuobj, 0x28, 0); 340 nvkm_wo32(*pgpuobj, 0x28, 0);
@@ -350,18 +351,13 @@ gf100_gr_chan_dtor(struct nvkm_object *object)
350 int i; 351 int i;
351 352
352 for (i = 0; i < ARRAY_SIZE(chan->data); i++) { 353 for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
353 if (chan->data[i].vma.node) { 354 nvkm_vmm_put(chan->vmm, &chan->data[i].vma);
354 nvkm_vm_unmap(&chan->data[i].vma); 355 nvkm_memory_unref(&chan->data[i].mem);
355 nvkm_vm_put(&chan->data[i].vma);
356 }
357 nvkm_memory_del(&chan->data[i].mem);
358 } 356 }
359 357
360 if (chan->mmio_vma.node) { 358 nvkm_vmm_put(chan->vmm, &chan->mmio_vma);
361 nvkm_vm_unmap(&chan->mmio_vma); 359 nvkm_memory_unref(&chan->mmio);
362 nvkm_vm_put(&chan->mmio_vma); 360 nvkm_vmm_unref(&chan->vmm);
363 }
364 nvkm_memory_del(&chan->mmio);
365 return chan; 361 return chan;
366} 362}
367 363
@@ -380,6 +376,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
380 struct gf100_gr_data *data = gr->mmio_data; 376 struct gf100_gr_data *data = gr->mmio_data;
381 struct gf100_gr_mmio *mmio = gr->mmio_list; 377 struct gf100_gr_mmio *mmio = gr->mmio_list;
382 struct gf100_gr_chan *chan; 378 struct gf100_gr_chan *chan;
379 struct gf100_vmm_map_v0 args = { .priv = 1 };
383 struct nvkm_device *device = gr->base.engine.subdev.device; 380 struct nvkm_device *device = gr->base.engine.subdev.device;
384 int ret, i; 381 int ret, i;
385 382
@@ -387,6 +384,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
387 return -ENOMEM; 384 return -ENOMEM;
388 nvkm_object_ctor(&gf100_gr_chan, oclass, &chan->object); 385 nvkm_object_ctor(&gf100_gr_chan, oclass, &chan->object);
389 chan->gr = gr; 386 chan->gr = gr;
387 chan->vmm = nvkm_vmm_ref(fifoch->vmm);
390 *pobject = &chan->object; 388 *pobject = &chan->object;
391 389
392 /* allocate memory for a "mmio list" buffer that's used by the HUB 390 /* allocate memory for a "mmio list" buffer that's used by the HUB
@@ -398,12 +396,14 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
398 if (ret) 396 if (ret)
399 return ret; 397 return ret;
400 398
401 ret = nvkm_vm_get(fifoch->vm, 0x1000, 12, NV_MEM_ACCESS_RW | 399 ret = nvkm_vmm_get(fifoch->vmm, 12, 0x1000, &chan->mmio_vma);
402 NV_MEM_ACCESS_SYS, &chan->mmio_vma);
403 if (ret) 400 if (ret)
404 return ret; 401 return ret;
405 402
406 nvkm_memory_map(chan->mmio, &chan->mmio_vma, 0); 403 ret = nvkm_memory_map(chan->mmio, 0, fifoch->vmm,
404 chan->mmio_vma, &args, sizeof(args));
405 if (ret)
406 return ret;
407 407
408 /* allocate buffers referenced by mmio list */ 408 /* allocate buffers referenced by mmio list */
409 for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) { 409 for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) {
@@ -413,13 +413,19 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
413 if (ret) 413 if (ret)
414 return ret; 414 return ret;
415 415
416 ret = nvkm_vm_get(fifoch->vm, 416 ret = nvkm_vmm_get(fifoch->vmm, 12,
417 nvkm_memory_size(chan->data[i].mem), 12, 417 nvkm_memory_size(chan->data[i].mem),
418 data->access, &chan->data[i].vma); 418 &chan->data[i].vma);
419 if (ret)
420 return ret;
421
422 args.priv = data->priv;
423
424 ret = nvkm_memory_map(chan->data[i].mem, 0, chan->vmm,
425 chan->data[i].vma, &args, sizeof(args));
419 if (ret) 426 if (ret)
420 return ret; 427 return ret;
421 428
422 nvkm_memory_map(chan->data[i].mem, &chan->data[i].vma, 0);
423 data++; 429 data++;
424 } 430 }
425 431
@@ -430,7 +436,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
430 u32 data = mmio->data; 436 u32 data = mmio->data;
431 437
432 if (mmio->buffer >= 0) { 438 if (mmio->buffer >= 0) {
433 u64 info = chan->data[mmio->buffer].vma.offset; 439 u64 info = chan->data[mmio->buffer].vma->addr;
434 data |= info >> mmio->shift; 440 data |= info >> mmio->shift;
435 } 441 }
436 442
@@ -1855,8 +1861,12 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
1855 int ret; 1861 int ret;
1856 1862
1857 ret = nvkm_firmware_get(device, fwname, &fw); 1863 ret = nvkm_firmware_get(device, fwname, &fw);
1858 if (ret) 1864 if (ret) {
1859 return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); 1865 ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
1866 if (ret)
1867 return -ENODEV;
1868 return 0;
1869 }
1860 1870
1861 fuc->size = fw->size; 1871 fuc->size = fw->size;
1862 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); 1872 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
@@ -1903,25 +1913,33 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,
1903 return 0; 1913 return 0;
1904} 1914}
1905 1915
1916void
1917gf100_gr_init_gpc_mmu(struct gf100_gr *gr)
1918{
1919 struct nvkm_device *device = gr->base.engine.subdev.device;
1920 struct nvkm_fb *fb = device->fb;
1921
1922 nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0x00000001);
1923 nvkm_wr32(device, 0x4188a4, 0x00000000);
1924 nvkm_wr32(device, 0x418888, 0x00000000);
1925 nvkm_wr32(device, 0x41888c, 0x00000000);
1926 nvkm_wr32(device, 0x418890, 0x00000000);
1927 nvkm_wr32(device, 0x418894, 0x00000000);
1928 nvkm_wr32(device, 0x4188b4, nvkm_memory_addr(fb->mmu_wr) >> 8);
1929 nvkm_wr32(device, 0x4188b8, nvkm_memory_addr(fb->mmu_rd) >> 8);
1930}
1931
1906int 1932int
1907gf100_gr_init(struct gf100_gr *gr) 1933gf100_gr_init(struct gf100_gr *gr)
1908{ 1934{
1909 struct nvkm_device *device = gr->base.engine.subdev.device; 1935 struct nvkm_device *device = gr->base.engine.subdev.device;
1910 struct nvkm_fb *fb = device->fb;
1911 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); 1936 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
1912 u32 data[TPC_MAX / 8] = {}; 1937 u32 data[TPC_MAX / 8] = {};
1913 u8 tpcnr[GPC_MAX]; 1938 u8 tpcnr[GPC_MAX];
1914 int gpc, tpc, rop; 1939 int gpc, tpc, rop;
1915 int i; 1940 int i;
1916 1941
1917 nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); 1942 gr->func->init_gpc_mmu(gr);
1918 nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000);
1919 nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000);
1920 nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
1921 nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
1922 nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
1923 nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8);
1924 nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8);
1925 1943
1926 gf100_gr_mmio(gr, gr->func->mmio); 1944 gf100_gr_mmio(gr, gr->func->mmio);
1927 1945
@@ -2036,6 +2054,7 @@ gf100_gr_gpccs_ucode = {
2036static const struct gf100_gr_func 2054static const struct gf100_gr_func
2037gf100_gr = { 2055gf100_gr = {
2038 .init = gf100_gr_init, 2056 .init = gf100_gr_init,
2057 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
2039 .mmio = gf100_gr_pack_mmio, 2058 .mmio = gf100_gr_pack_mmio,
2040 .fecs.ucode = &gf100_gr_fecs_ucode, 2059 .fecs.ucode = &gf100_gr_fecs_ucode,
2041 .gpccs.ucode = &gf100_gr_gpccs_ucode, 2060 .gpccs.ucode = &gf100_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
index a36e45a4a635..d7c2adb9b543 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
@@ -45,7 +45,7 @@
45struct gf100_gr_data { 45struct gf100_gr_data {
46 u32 size; 46 u32 size;
47 u32 align; 47 u32 align;
48 u32 access; 48 bool priv;
49}; 49};
50 50
51struct gf100_gr_mmio { 51struct gf100_gr_mmio {
@@ -156,18 +156,20 @@ int gp100_gr_init(struct gf100_gr *);
156void gp100_gr_init_rop_active_fbps(struct gf100_gr *); 156void gp100_gr_init_rop_active_fbps(struct gf100_gr *);
157 157
158#define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) 158#define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object)
159#include <core/object.h>
159 160
160struct gf100_gr_chan { 161struct gf100_gr_chan {
161 struct nvkm_object object; 162 struct nvkm_object object;
162 struct gf100_gr *gr; 163 struct gf100_gr *gr;
164 struct nvkm_vmm *vmm;
163 165
164 struct nvkm_memory *mmio; 166 struct nvkm_memory *mmio;
165 struct nvkm_vma mmio_vma; 167 struct nvkm_vma *mmio_vma;
166 int mmio_nr; 168 int mmio_nr;
167 169
168 struct { 170 struct {
169 struct nvkm_memory *mem; 171 struct nvkm_memory *mem;
170 struct nvkm_vma vma; 172 struct nvkm_vma *vma;
171 } data[4]; 173 } data[4];
172}; 174};
173 175
@@ -253,6 +255,7 @@ extern const struct gf100_gr_init gf100_gr_init_mpc_0[];
253extern const struct gf100_gr_init gf100_gr_init_be_0[]; 255extern const struct gf100_gr_init gf100_gr_init_be_0[];
254extern const struct gf100_gr_init gf100_gr_init_fe_1[]; 256extern const struct gf100_gr_init gf100_gr_init_fe_1[];
255extern const struct gf100_gr_init gf100_gr_init_pe_1[]; 257extern const struct gf100_gr_init gf100_gr_init_pe_1[];
258void gf100_gr_init_gpc_mmu(struct gf100_gr *);
256 259
257extern const struct gf100_gr_init gf104_gr_init_ds_0[]; 260extern const struct gf100_gr_init gf104_gr_init_ds_0[];
258extern const struct gf100_gr_init gf104_gr_init_tex_0[]; 261extern const struct gf100_gr_init gf104_gr_init_tex_0[];
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
index d736dcd55ea2..ec0f11983b23 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
@@ -115,6 +115,7 @@ gf104_gr_pack_mmio[] = {
115static const struct gf100_gr_func 115static const struct gf100_gr_func
116gf104_gr = { 116gf104_gr = {
117 .init = gf100_gr_init, 117 .init = gf100_gr_init,
118 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
118 .mmio = gf104_gr_pack_mmio, 119 .mmio = gf104_gr_pack_mmio,
119 .fecs.ucode = &gf100_gr_fecs_ucode, 120 .fecs.ucode = &gf100_gr_fecs_ucode,
120 .gpccs.ucode = &gf100_gr_gpccs_ucode, 121 .gpccs.ucode = &gf100_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
index 2f0d24498427..cc152eb74123 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
@@ -106,6 +106,7 @@ gf108_gr_pack_mmio[] = {
106static const struct gf100_gr_func 106static const struct gf100_gr_func
107gf108_gr = { 107gf108_gr = {
108 .init = gf100_gr_init, 108 .init = gf100_gr_init,
109 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
109 .mmio = gf108_gr_pack_mmio, 110 .mmio = gf108_gr_pack_mmio,
110 .fecs.ucode = &gf100_gr_fecs_ucode, 111 .fecs.ucode = &gf100_gr_fecs_ucode,
111 .gpccs.ucode = &gf100_gr_gpccs_ucode, 112 .gpccs.ucode = &gf100_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
index d1d942eb86af..10d2d73ca8c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
@@ -87,6 +87,7 @@ gf110_gr_pack_mmio[] = {
87static const struct gf100_gr_func 87static const struct gf100_gr_func
88gf110_gr = { 88gf110_gr = {
89 .init = gf100_gr_init, 89 .init = gf100_gr_init,
90 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
90 .mmio = gf110_gr_pack_mmio, 91 .mmio = gf110_gr_pack_mmio,
91 .fecs.ucode = &gf100_gr_fecs_ucode, 92 .fecs.ucode = &gf100_gr_fecs_ucode,
92 .gpccs.ucode = &gf100_gr_gpccs_ucode, 93 .gpccs.ucode = &gf100_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
index 0124e468086e..ac09a07c4150 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
@@ -123,6 +123,7 @@ gf117_gr_gpccs_ucode = {
123static const struct gf100_gr_func 123static const struct gf100_gr_func
124gf117_gr = { 124gf117_gr = {
125 .init = gf100_gr_init, 125 .init = gf100_gr_init,
126 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
126 .mmio = gf117_gr_pack_mmio, 127 .mmio = gf117_gr_pack_mmio,
127 .fecs.ucode = &gf117_gr_fecs_ucode, 128 .fecs.ucode = &gf117_gr_fecs_ucode,
128 .gpccs.ucode = &gf117_gr_gpccs_ucode, 129 .gpccs.ucode = &gf117_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
index 8d8e4cafe28f..7f449ec6f760 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
@@ -178,6 +178,7 @@ gf119_gr_pack_mmio[] = {
178static const struct gf100_gr_func 178static const struct gf100_gr_func
179gf119_gr = { 179gf119_gr = {
180 .init = gf100_gr_init, 180 .init = gf100_gr_init,
181 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
181 .mmio = gf119_gr_pack_mmio, 182 .mmio = gf119_gr_pack_mmio,
182 .fecs.ucode = &gf100_gr_fecs_ucode, 183 .fecs.ucode = &gf100_gr_fecs_ucode,
183 .gpccs.ucode = &gf100_gr_gpccs_ucode, 184 .gpccs.ucode = &gf100_gr_gpccs_ucode,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
index ec22da6c99fc..5e82f94c2245 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
@@ -24,8 +24,6 @@
24#include "gf100.h" 24#include "gf100.h"
25#include "ctxgf100.h" 25#include "ctxgf100.h"
26 26
27#include <subdev/fb.h>
28
29#include <nvif/class.h> 27#include <nvif/class.h>
30 28
31/******************************************************************************* 29/*******************************************************************************
@@ -207,21 +205,13 @@ int
207gk104_gr_init(struct gf100_gr *gr) 205gk104_gr_init(struct gf100_gr *gr)
208{ 206{
209 struct nvkm_device *device = gr->base.engine.subdev.device; 207 struct nvkm_device *device = gr->base.engine.subdev.device;
210 struct nvkm_fb *fb = device->fb;
211 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); 208 const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
212 u32 data[TPC_MAX / 8] = {}; 209 u32 data[TPC_MAX / 8] = {};
213 u8 tpcnr[GPC_MAX]; 210 u8 tpcnr[GPC_MAX];
214 int gpc, tpc, rop; 211 int gpc, tpc, rop;
215 int i; 212 int i;
216 213
217 nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); 214 gr->func->init_gpc_mmu(gr);
218 nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000);
219 nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000);
220 nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
221 nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
222 nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
223 nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8);
224 nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8);
225 215
226 gf100_gr_mmio(gr, gr->func->mmio); 216 gf100_gr_mmio(gr, gr->func->mmio);
227 217
@@ -339,6 +329,7 @@ gk104_gr_gpccs_ucode = {
339static const struct gf100_gr_func 329static const struct gf100_gr_func
340gk104_gr = { 330gk104_gr = {
341 .init = gk104_gr_init, 331 .init = gk104_gr_init,
332 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
342 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, 333 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
343 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, 334 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
344 .mmio = gk104_gr_pack_mmio, 335 .mmio = gk104_gr_pack_mmio,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
index f31b171a4102..a38e19b61c1d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
@@ -183,6 +183,7 @@ gk110_gr_gpccs_ucode = {
183static const struct gf100_gr_func 183static const struct gf100_gr_func
184gk110_gr = { 184gk110_gr = {
185 .init = gk104_gr_init, 185 .init = gk104_gr_init,
186 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
186 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, 187 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
187 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, 188 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
188 .mmio = gk110_gr_pack_mmio, 189 .mmio = gk110_gr_pack_mmio,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
index d76dd178007f..1912c0bfd7ee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
@@ -103,6 +103,7 @@ gk110b_gr_pack_mmio[] = {
103static const struct gf100_gr_func 103static const struct gf100_gr_func
104gk110b_gr = { 104gk110b_gr = {
105 .init = gk104_gr_init, 105 .init = gk104_gr_init,
106 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
106 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, 107 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
107 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, 108 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
108 .mmio = gk110b_gr_pack_mmio, 109 .mmio = gk110b_gr_pack_mmio,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
index 14bbe6ed02a9..1fc258163f25 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
@@ -162,6 +162,7 @@ gk208_gr_gpccs_ucode = {
162static const struct gf100_gr_func 162static const struct gf100_gr_func
163gk208_gr = { 163gk208_gr = {
164 .init = gk104_gr_init, 164 .init = gk104_gr_init,
165 .init_gpc_mmu = gf100_gr_init_gpc_mmu,
165 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, 166 .init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
166 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, 167 .init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
167 .mmio = gk208_gr_pack_mmio, 168 .mmio = gk208_gr_pack_mmio,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
index d1dc92999dc0..d6840dc81a29 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
@@ -59,7 +59,7 @@ void *
59nv20_gr_chan_dtor(struct nvkm_object *object) 59nv20_gr_chan_dtor(struct nvkm_object *object)
60{ 60{
61 struct nv20_gr_chan *chan = nv20_gr_chan(object); 61 struct nv20_gr_chan *chan = nv20_gr_chan(object);
62 nvkm_memory_del(&chan->inst); 62 nvkm_memory_unref(&chan->inst);
63 return chan; 63 return chan;
64} 64}
65 65
@@ -323,7 +323,7 @@ void *
323nv20_gr_dtor(struct nvkm_gr *base) 323nv20_gr_dtor(struct nvkm_gr *base)
324{ 324{
325 struct nv20_gr *gr = nv20_gr(base); 325 struct nv20_gr *gr = nv20_gr(base);
326 nvkm_memory_del(&gr->ctxtab); 326 nvkm_memory_unref(&gr->ctxtab);
327 return gr; 327 return gr;
328} 328}
329 329
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
index cdf4501e3798..d0cb2b8846ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h
@@ -19,6 +19,7 @@ void nv20_gr_tile(struct nvkm_gr *, int, struct nvkm_fb_tile *);
19int nv30_gr_init(struct nvkm_gr *); 19int nv30_gr_init(struct nvkm_gr *);
20 20
21#define nv20_gr_chan(p) container_of((p), struct nv20_gr_chan, object) 21#define nv20_gr_chan(p) container_of((p), struct nv20_gr_chan, object)
22#include <core/object.h>
22 23
23struct nv20_gr_chan { 24struct nv20_gr_chan {
24 struct nvkm_object object; 25 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
index 2812ed11f877..bee8ef2d5697 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h
@@ -16,6 +16,7 @@ void nv40_gr_intr(struct nvkm_gr *);
16u64 nv40_gr_units(struct nvkm_gr *); 16u64 nv40_gr_units(struct nvkm_gr *);
17 17
18#define nv40_gr_chan(p) container_of((p), struct nv40_gr_chan, object) 18#define nv40_gr_chan(p) container_of((p), struct nv40_gr_chan, object)
19#include <core/object.h>
19 20
20struct nv40_gr_chan { 21struct nv40_gr_chan {
21 struct nvkm_object object; 22 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
index 45eec83a5969..1ab6ea436b70 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h
@@ -19,6 +19,7 @@ u64 nv50_gr_units(struct nvkm_gr *);
19int g84_gr_tlb_flush(struct nvkm_gr *); 19int g84_gr_tlb_flush(struct nvkm_gr *);
20 20
21#define nv50_gr_chan(p) container_of((p), struct nv50_gr_chan, object) 21#define nv50_gr_chan(p) container_of((p), struct nv50_gr_chan, object)
22#include <core/object.h>
22 23
23struct nv50_gr_chan { 24struct nv50_gr_chan {
24 struct nvkm_object object; 25 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
index d3bb34fcdebf..f0d35beb58df 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h
@@ -18,6 +18,7 @@ struct nv31_mpeg_func {
18}; 18};
19 19
20#define nv31_mpeg_chan(p) container_of((p), struct nv31_mpeg_chan, object) 20#define nv31_mpeg_chan(p) container_of((p), struct nv31_mpeg_chan, object)
21#include <core/object.h>
21 22
22struct nv31_mpeg_chan { 23struct nv31_mpeg_chan {
23 struct nvkm_object object; 24 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c
index 4e528851e9c0..6df880a39019 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c
@@ -24,6 +24,7 @@
24#include "priv.h" 24#include "priv.h"
25 25
26#include <core/gpuobj.h> 26#include <core/gpuobj.h>
27#include <core/object.h>
27#include <subdev/timer.h> 28#include <subdev/timer.h>
28 29
29#include <nvif/class.h> 30#include <nvif/class.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
index d7b81cbf82b5..4ff0475e776c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h
@@ -67,6 +67,7 @@ struct nvkm_specdom {
67}; 67};
68 68
69#define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object) 69#define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object)
70#include <core/object.h>
70 71
71struct nvkm_perfdom { 72struct nvkm_perfdom {
72 struct nvkm_object object; 73 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
index 6608bf6c6842..b5be49f0ac56 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
@@ -1,9 +1,11 @@
1#ifndef __NVKM_SW_CHAN_H__ 1#ifndef __NVKM_SW_CHAN_H__
2#define __NVKM_SW_CHAN_H__ 2#define __NVKM_SW_CHAN_H__
3#define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object) 3#define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object)
4#include "priv.h" 4#include <core/object.h>
5#include <core/event.h> 5#include <core/event.h>
6 6
7#include "priv.h"
8
7struct nvkm_sw_chan { 9struct nvkm_sw_chan {
8 const struct nvkm_sw_chan_func *func; 10 const struct nvkm_sw_chan_func *func;
9 struct nvkm_object object; 11 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
index 943ef4c10091..bcfff62131fe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h
@@ -1,7 +1,7 @@
1#ifndef __NVKM_NVSW_H__ 1#ifndef __NVKM_NVSW_H__
2#define __NVKM_NVSW_H__ 2#define __NVKM_NVSW_H__
3#define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object) 3#define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object)
4#include "priv.h" 4#include <core/object.h>
5 5
6struct nvkm_nvsw { 6struct nvkm_nvsw {
7 struct nvkm_object object; 7 struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
index 06bdb67a0205..70549381e082 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
@@ -86,7 +86,7 @@ nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend)
86 nvkm_wr32(device, base + 0xd94, 0); /* FIFO_CTRL */ 86 nvkm_wr32(device, base + 0xd94, 0); /* FIFO_CTRL */
87 87
88 if (!suspend) 88 if (!suspend)
89 nvkm_memory_del(&xtensa->gpu_fw); 89 nvkm_memory_unref(&xtensa->gpu_fw);
90 return 0; 90 return 0;
91} 91}
92 92
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
index 1b7f48efd8b1..14be41f24155 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
@@ -60,7 +60,7 @@ nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port,
60} 60}
61 61
62void 62void
63nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *inst) 63nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *inst)
64{ 64{
65 if (!falcon->func->bind_context) { 65 if (!falcon->func->bind_context) {
66 nvkm_error(falcon->user, 66 nvkm_error(falcon->user,
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
index 669c24028470..9def926f24d4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
@@ -180,7 +180,7 @@ nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size,
180} 180}
181 181
182static void 182static void
183nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) 183nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx)
184{ 184{
185 u32 inst_loc; 185 u32 inst_loc;
186 u32 fbif; 186 u32 fbif;
@@ -216,7 +216,7 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx)
216 nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); 216 nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6);
217 217
218 /* Set context */ 218 /* Set context */
219 switch (nvkm_memory_target(ctx->memory)) { 219 switch (nvkm_memory_target(ctx)) {
220 case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break; 220 case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break;
221 case NVKM_MEM_TARGET_HOST: inst_loc = 2; break; 221 case NVKM_MEM_TARGET_HOST: inst_loc = 2; break;
222 case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break; 222 case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break;
@@ -228,7 +228,7 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx)
228 /* Enable context */ 228 /* Enable context */
229 nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); 229 nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1);
230 nvkm_falcon_wr32(falcon, 0x054, 230 nvkm_falcon_wr32(falcon, 0x054,
231 ((ctx->addr >> 12) & 0xfffffff) | 231 ((nvkm_memory_addr(ctx) >> 12) & 0xfffffff) |
232 (inst_loc << 28) | (1 << 30)); 232 (inst_loc << 28) | (1 << 30));
233 233
234 nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000); 234 nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild
index 1e138b337955..e5830453813d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild
@@ -3,3 +3,5 @@ nvkm-y += nvkm/subdev/bar/nv50.o
3nvkm-y += nvkm/subdev/bar/g84.o 3nvkm-y += nvkm/subdev/bar/g84.o
4nvkm-y += nvkm/subdev/bar/gf100.o 4nvkm-y += nvkm/subdev/bar/gf100.o
5nvkm-y += nvkm/subdev/bar/gk20a.o 5nvkm-y += nvkm/subdev/bar/gk20a.o
6nvkm-y += nvkm/subdev/bar/gm107.o
7nvkm-y += nvkm/subdev/bar/gm20b.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
index c561d148cebc..9646adec57cb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
@@ -30,39 +30,76 @@ nvkm_bar_flush(struct nvkm_bar *bar)
30 bar->func->flush(bar); 30 bar->func->flush(bar);
31} 31}
32 32
33struct nvkm_vm * 33struct nvkm_vmm *
34nvkm_bar_kmap(struct nvkm_bar *bar) 34nvkm_bar_bar1_vmm(struct nvkm_device *device)
35{ 35{
36 /* disallow kmap() until after vm has been bootstrapped */ 36 return device->bar->func->bar1.vmm(device->bar);
37 if (bar && bar->func->kmap && bar->subdev.oneinit) 37}
38 return bar->func->kmap(bar); 38
39struct nvkm_vmm *
40nvkm_bar_bar2_vmm(struct nvkm_device *device)
41{
42 /* Denies access to BAR2 when it's not initialised, used by INSTMEM
43 * to know when object access needs to go through the BAR0 window.
44 */
45 struct nvkm_bar *bar = device->bar;
46 if (bar && bar->bar2)
47 return bar->func->bar2.vmm(bar);
39 return NULL; 48 return NULL;
40} 49}
41 50
42int 51void
43nvkm_bar_umap(struct nvkm_bar *bar, u64 size, int type, struct nvkm_vma *vma) 52nvkm_bar_bar2_fini(struct nvkm_device *device)
44{ 53{
45 return bar->func->umap(bar, size, type, vma); 54 struct nvkm_bar *bar = device->bar;
55 if (bar && bar->bar2) {
56 bar->func->bar2.fini(bar);
57 bar->bar2 = false;
58 }
59}
60
61void
62nvkm_bar_bar2_init(struct nvkm_device *device)
63{
64 struct nvkm_bar *bar = device->bar;
65 if (bar && bar->subdev.oneinit && !bar->bar2 && bar->func->bar2.init) {
66 bar->func->bar2.init(bar);
67 bar->func->bar2.wait(bar);
68 bar->bar2 = true;
69 }
46} 70}
47 71
48static int 72static int
49nvkm_bar_oneinit(struct nvkm_subdev *subdev) 73nvkm_bar_fini(struct nvkm_subdev *subdev, bool suspend)
50{ 74{
51 struct nvkm_bar *bar = nvkm_bar(subdev); 75 struct nvkm_bar *bar = nvkm_bar(subdev);
52 return bar->func->oneinit(bar); 76 bar->func->bar1.fini(bar);
77 return 0;
53} 78}
54 79
55static int 80static int
56nvkm_bar_init(struct nvkm_subdev *subdev) 81nvkm_bar_init(struct nvkm_subdev *subdev)
57{ 82{
58 struct nvkm_bar *bar = nvkm_bar(subdev); 83 struct nvkm_bar *bar = nvkm_bar(subdev);
59 return bar->func->init(bar); 84 bar->func->bar1.init(bar);
85 bar->func->bar1.wait(bar);
86 if (bar->func->init)
87 bar->func->init(bar);
88 return 0;
89}
90
91static int
92nvkm_bar_oneinit(struct nvkm_subdev *subdev)
93{
94 struct nvkm_bar *bar = nvkm_bar(subdev);
95 return bar->func->oneinit(bar);
60} 96}
61 97
62static void * 98static void *
63nvkm_bar_dtor(struct nvkm_subdev *subdev) 99nvkm_bar_dtor(struct nvkm_subdev *subdev)
64{ 100{
65 struct nvkm_bar *bar = nvkm_bar(subdev); 101 struct nvkm_bar *bar = nvkm_bar(subdev);
102 nvkm_bar_bar2_fini(subdev->device);
66 return bar->func->dtor(bar); 103 return bar->func->dtor(bar);
67} 104}
68 105
@@ -71,6 +108,7 @@ nvkm_bar = {
71 .dtor = nvkm_bar_dtor, 108 .dtor = nvkm_bar_dtor,
72 .oneinit = nvkm_bar_oneinit, 109 .oneinit = nvkm_bar_oneinit,
73 .init = nvkm_bar_init, 110 .init = nvkm_bar_init,
111 .fini = nvkm_bar_fini,
74}; 112};
75 113
76void 114void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c
index ef717136c838..87f26f54b481 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c
@@ -44,8 +44,14 @@ g84_bar_func = {
44 .dtor = nv50_bar_dtor, 44 .dtor = nv50_bar_dtor,
45 .oneinit = nv50_bar_oneinit, 45 .oneinit = nv50_bar_oneinit,
46 .init = nv50_bar_init, 46 .init = nv50_bar_init,
47 .kmap = nv50_bar_kmap, 47 .bar1.init = nv50_bar_bar1_init,
48 .umap = nv50_bar_umap, 48 .bar1.fini = nv50_bar_bar1_fini,
49 .bar1.wait = nv50_bar_bar1_wait,
50 .bar1.vmm = nv50_bar_bar1_vmm,
51 .bar2.init = nv50_bar_bar2_init,
52 .bar2.fini = nv50_bar_bar2_fini,
53 .bar2.wait = nv50_bar_bar1_wait,
54 .bar2.vmm = nv50_bar_bar2_vmm,
49 .flush = g84_bar_flush, 55 .flush = g84_bar_flush,
50}; 56};
51 57
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
index 676c167c95b9..a3ba7f50198b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
@@ -23,39 +23,73 @@
23 */ 23 */
24#include "gf100.h" 24#include "gf100.h"
25 25
26#include <core/gpuobj.h> 26#include <core/memory.h>
27#include <core/option.h> 27#include <core/option.h>
28#include <subdev/fb.h> 28#include <subdev/fb.h>
29#include <subdev/mmu.h> 29#include <subdev/mmu.h>
30 30
31static struct nvkm_vm * 31struct nvkm_vmm *
32gf100_bar_kmap(struct nvkm_bar *base) 32gf100_bar_bar1_vmm(struct nvkm_bar *base)
33{ 33{
34 return gf100_bar(base)->bar[0].vm; 34 return gf100_bar(base)->bar[1].vmm;
35} 35}
36 36
37int 37void
38gf100_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) 38gf100_bar_bar1_wait(struct nvkm_bar *base)
39{
40 /* NFI why it's twice. */
41 nvkm_bar_flush(base);
42 nvkm_bar_flush(base);
43}
44
45void
46gf100_bar_bar1_fini(struct nvkm_bar *bar)
39{ 47{
48 nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000);
49}
50
51void
52gf100_bar_bar1_init(struct nvkm_bar *base)
53{
54 struct nvkm_device *device = base->subdev.device;
40 struct gf100_bar *bar = gf100_bar(base); 55 struct gf100_bar *bar = gf100_bar(base);
41 return nvkm_vm_get(bar->bar[1].vm, size, type, NV_MEM_ACCESS_RW, vma); 56 const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
57 nvkm_wr32(device, 0x001704, 0x80000000 | addr);
58}
59
60struct nvkm_vmm *
61gf100_bar_bar2_vmm(struct nvkm_bar *base)
62{
63 return gf100_bar(base)->bar[0].vmm;
64}
65
66void
67gf100_bar_bar2_fini(struct nvkm_bar *bar)
68{
69 nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000);
70}
71
72void
73gf100_bar_bar2_init(struct nvkm_bar *base)
74{
75 struct nvkm_device *device = base->subdev.device;
76 struct gf100_bar *bar = gf100_bar(base);
77 u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
78 if (bar->bar2_halve)
79 addr |= 0x40000000;
80 nvkm_wr32(device, 0x001714, 0x80000000 | addr);
42} 81}
43 82
44static int 83static int
45gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, 84gf100_bar_oneinit_bar(struct gf100_bar *bar, struct gf100_barN *bar_vm,
46 struct lock_class_key *key, int bar_nr) 85 struct lock_class_key *key, int bar_nr)
47{ 86{
48 struct nvkm_device *device = bar->base.subdev.device; 87 struct nvkm_device *device = bar->base.subdev.device;
49 struct nvkm_vm *vm;
50 resource_size_t bar_len; 88 resource_size_t bar_len;
51 int ret; 89 int ret;
52 90
53 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false, 91 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false,
54 &bar_vm->mem); 92 &bar_vm->inst);
55 if (ret)
56 return ret;
57
58 ret = nvkm_gpuobj_new(device, 0x8000, 0, false, NULL, &bar_vm->pgd);
59 if (ret) 93 if (ret)
60 return ret; 94 return ret;
61 95
@@ -63,98 +97,64 @@ gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm,
63 if (bar_nr == 3 && bar->bar2_halve) 97 if (bar_nr == 3 && bar->bar2_halve)
64 bar_len >>= 1; 98 bar_len >>= 1;
65 99
66 ret = nvkm_vm_new(device, 0, bar_len, 0, key, &vm); 100 ret = nvkm_vmm_new(device, 0, bar_len, NULL, 0, key,
101 (bar_nr == 3) ? "bar2" : "bar1", &bar_vm->vmm);
67 if (ret) 102 if (ret)
68 return ret; 103 return ret;
69 104
70 atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); 105 atomic_inc(&bar_vm->vmm->engref[NVKM_SUBDEV_BAR]);
106 bar_vm->vmm->debug = bar->base.subdev.debug;
71 107
72 /* 108 /*
73 * Bootstrap page table lookup. 109 * Bootstrap page table lookup.
74 */ 110 */
75 if (bar_nr == 3) { 111 if (bar_nr == 3) {
76 ret = nvkm_vm_boot(vm, bar_len); 112 ret = nvkm_vmm_boot(bar_vm->vmm);
77 if (ret) { 113 if (ret)
78 nvkm_vm_ref(NULL, &vm, NULL);
79 return ret; 114 return ret;
80 }
81 } 115 }
82 116
83 ret = nvkm_vm_ref(vm, &bar_vm->vm, bar_vm->pgd); 117 return nvkm_vmm_join(bar_vm->vmm, bar_vm->inst);
84 nvkm_vm_ref(NULL, &vm, NULL);
85 if (ret)
86 return ret;
87
88 nvkm_kmap(bar_vm->mem);
89 nvkm_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr));
90 nvkm_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr));
91 nvkm_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1));
92 nvkm_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1));
93 nvkm_done(bar_vm->mem);
94 return 0;
95} 118}
96 119
97int 120int
98gf100_bar_oneinit(struct nvkm_bar *base) 121gf100_bar_oneinit(struct nvkm_bar *base)
99{ 122{
100 static struct lock_class_key bar1_lock; 123 static struct lock_class_key bar1_lock;
101 static struct lock_class_key bar3_lock; 124 static struct lock_class_key bar2_lock;
102 struct gf100_bar *bar = gf100_bar(base); 125 struct gf100_bar *bar = gf100_bar(base);
103 int ret; 126 int ret;
104 127
105 /* BAR3 */ 128 /* BAR2 */
106 if (bar->base.func->kmap) { 129 if (bar->base.func->bar2.init) {
107 ret = gf100_bar_ctor_vm(bar, &bar->bar[0], &bar3_lock, 3); 130 ret = gf100_bar_oneinit_bar(bar, &bar->bar[0], &bar2_lock, 3);
108 if (ret) 131 if (ret)
109 return ret; 132 return ret;
133
134 bar->base.subdev.oneinit = true;
135 nvkm_bar_bar2_init(bar->base.subdev.device);
110 } 136 }
111 137
112 /* BAR1 */ 138 /* BAR1 */
113 ret = gf100_bar_ctor_vm(bar, &bar->bar[1], &bar1_lock, 1); 139 ret = gf100_bar_oneinit_bar(bar, &bar->bar[1], &bar1_lock, 1);
114 if (ret) 140 if (ret)
115 return ret; 141 return ret;
116 142
117 return 0; 143 return 0;
118} 144}
119 145
120int
121gf100_bar_init(struct nvkm_bar *base)
122{
123 struct gf100_bar *bar = gf100_bar(base);
124 struct nvkm_device *device = bar->base.subdev.device;
125 u32 addr;
126
127 nvkm_mask(device, 0x000200, 0x00000100, 0x00000000);
128 nvkm_mask(device, 0x000200, 0x00000100, 0x00000100);
129
130 addr = nvkm_memory_addr(bar->bar[1].mem) >> 12;
131 nvkm_wr32(device, 0x001704, 0x80000000 | addr);
132
133 if (bar->bar[0].mem) {
134 addr = nvkm_memory_addr(bar->bar[0].mem) >> 12;
135 if (bar->bar2_halve)
136 addr |= 0x40000000;
137 nvkm_wr32(device, 0x001714, 0x80000000 | addr);
138 }
139
140 return 0;
141}
142
143void * 146void *
144gf100_bar_dtor(struct nvkm_bar *base) 147gf100_bar_dtor(struct nvkm_bar *base)
145{ 148{
146 struct gf100_bar *bar = gf100_bar(base); 149 struct gf100_bar *bar = gf100_bar(base);
147 150
148 nvkm_vm_ref(NULL, &bar->bar[1].vm, bar->bar[1].pgd); 151 nvkm_vmm_part(bar->bar[1].vmm, bar->bar[1].inst);
149 nvkm_gpuobj_del(&bar->bar[1].pgd); 152 nvkm_vmm_unref(&bar->bar[1].vmm);
150 nvkm_memory_del(&bar->bar[1].mem); 153 nvkm_memory_unref(&bar->bar[1].inst);
151 154
152 if (bar->bar[0].vm) { 155 nvkm_vmm_part(bar->bar[0].vmm, bar->bar[0].inst);
153 nvkm_memory_del(&bar->bar[0].vm->pgt[0].mem[0]); 156 nvkm_vmm_unref(&bar->bar[0].vmm);
154 nvkm_vm_ref(NULL, &bar->bar[0].vm, bar->bar[0].pgd); 157 nvkm_memory_unref(&bar->bar[0].inst);
155 }
156 nvkm_gpuobj_del(&bar->bar[0].pgd);
157 nvkm_memory_del(&bar->bar[0].mem);
158 return bar; 158 return bar;
159} 159}
160 160
@@ -175,9 +175,14 @@ static const struct nvkm_bar_func
175gf100_bar_func = { 175gf100_bar_func = {
176 .dtor = gf100_bar_dtor, 176 .dtor = gf100_bar_dtor,
177 .oneinit = gf100_bar_oneinit, 177 .oneinit = gf100_bar_oneinit,
178 .init = gf100_bar_init, 178 .bar1.init = gf100_bar_bar1_init,
179 .kmap = gf100_bar_kmap, 179 .bar1.fini = gf100_bar_bar1_fini,
180 .umap = gf100_bar_umap, 180 .bar1.wait = gf100_bar_bar1_wait,
181 .bar1.vmm = gf100_bar_bar1_vmm,
182 .bar2.init = gf100_bar_bar2_init,
183 .bar2.fini = gf100_bar_bar2_fini,
184 .bar2.wait = gf100_bar_bar1_wait,
185 .bar2.vmm = gf100_bar_bar2_vmm,
181 .flush = g84_bar_flush, 186 .flush = g84_bar_flush,
182}; 187};
183 188
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
index 20a5255362ba..e4da39139e95 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h
@@ -3,22 +3,24 @@
3#define gf100_bar(p) container_of((p), struct gf100_bar, base) 3#define gf100_bar(p) container_of((p), struct gf100_bar, base)
4#include "priv.h" 4#include "priv.h"
5 5
6struct gf100_bar_vm { 6struct gf100_barN {
7 struct nvkm_memory *mem; 7 struct nvkm_memory *inst;
8 struct nvkm_gpuobj *pgd; 8 struct nvkm_vmm *vmm;
9 struct nvkm_vm *vm;
10}; 9};
11 10
12struct gf100_bar { 11struct gf100_bar {
13 struct nvkm_bar base; 12 struct nvkm_bar base;
14 bool bar2_halve; 13 bool bar2_halve;
15 struct gf100_bar_vm bar[2]; 14 struct gf100_barN bar[2];
16}; 15};
17 16
18int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, 17int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *,
19 int, struct nvkm_bar **); 18 int, struct nvkm_bar **);
20void *gf100_bar_dtor(struct nvkm_bar *); 19void *gf100_bar_dtor(struct nvkm_bar *);
21int gf100_bar_oneinit(struct nvkm_bar *); 20int gf100_bar_oneinit(struct nvkm_bar *);
22int gf100_bar_init(struct nvkm_bar *); 21void gf100_bar_bar1_init(struct nvkm_bar *);
23int gf100_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); 22void gf100_bar_bar1_wait(struct nvkm_bar *);
23struct nvkm_vmm *gf100_bar_bar1_vmm(struct nvkm_bar *);
24void gf100_bar_bar2_init(struct nvkm_bar *);
25struct nvkm_vmm *gf100_bar_bar2_vmm(struct nvkm_bar *);
24#endif 26#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c
index 9232fab4274c..b10077d38839 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c
@@ -25,8 +25,10 @@ static const struct nvkm_bar_func
25gk20a_bar_func = { 25gk20a_bar_func = {
26 .dtor = gf100_bar_dtor, 26 .dtor = gf100_bar_dtor,
27 .oneinit = gf100_bar_oneinit, 27 .oneinit = gf100_bar_oneinit,
28 .init = gf100_bar_init, 28 .bar1.init = gf100_bar_bar1_init,
29 .umap = gf100_bar_umap, 29 .bar1.fini = gf100_bar_bar1_fini,
30 .bar1.wait = gf100_bar_bar1_wait,
31 .bar1.vmm = gf100_bar_bar1_vmm,
30 .flush = g84_bar_flush, 32 .flush = g84_bar_flush,
31}; 33};
32 34
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c
new file mode 100644
index 000000000000..3ddf9222d935
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c
@@ -0,0 +1,65 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "gf100.h"
23
24#include <subdev/timer.h>
25
26void
27gm107_bar_bar1_wait(struct nvkm_bar *bar)
28{
29 struct nvkm_device *device = bar->subdev.device;
30 nvkm_msec(device, 2000,
31 if (!(nvkm_rd32(device, 0x001710) & 0x00000003))
32 break;
33 );
34}
35
36static void
37gm107_bar_bar2_wait(struct nvkm_bar *bar)
38{
39 struct nvkm_device *device = bar->subdev.device;
40 nvkm_msec(device, 2000,
41 if (!(nvkm_rd32(device, 0x001710) & 0x0000000c))
42 break;
43 );
44}
45
46static const struct nvkm_bar_func
47gm107_bar_func = {
48 .dtor = gf100_bar_dtor,
49 .oneinit = gf100_bar_oneinit,
50 .bar1.init = gf100_bar_bar1_init,
51 .bar1.fini = gf100_bar_bar1_fini,
52 .bar1.wait = gm107_bar_bar1_wait,
53 .bar1.vmm = gf100_bar_bar1_vmm,
54 .bar2.init = gf100_bar_bar2_init,
55 .bar2.fini = gf100_bar_bar2_fini,
56 .bar2.wait = gm107_bar_bar2_wait,
57 .bar2.vmm = gf100_bar_bar2_vmm,
58 .flush = g84_bar_flush,
59};
60
61int
62gm107_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar)
63{
64 return gf100_bar_new_(&gm107_bar_func, device, index, pbar);
65}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c
new file mode 100644
index 000000000000..950bff1955ad
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "gf100.h"
23
24static const struct nvkm_bar_func
25gm20b_bar_func = {
26 .dtor = gf100_bar_dtor,
27 .oneinit = gf100_bar_oneinit,
28 .bar1.init = gf100_bar_bar1_init,
29 .bar1.fini = gf100_bar_bar1_fini,
30 .bar1.wait = gm107_bar_bar1_wait,
31 .bar1.vmm = gf100_bar_bar1_vmm,
32 .flush = g84_bar_flush,
33};
34
35int
36gm20b_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar)
37{
38 int ret = gf100_bar_new_(&gm20b_bar_func, device, index, pbar);
39 if (ret == 0)
40 (*pbar)->iomap_uncached = true;
41 return ret;
42}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
index 6eff637ac301..157b076a1272 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
@@ -28,19 +28,6 @@
28#include <subdev/mmu.h> 28#include <subdev/mmu.h>
29#include <subdev/timer.h> 29#include <subdev/timer.h>
30 30
31struct nvkm_vm *
32nv50_bar_kmap(struct nvkm_bar *base)
33{
34 return nv50_bar(base)->bar3_vm;
35}
36
37int
38nv50_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma)
39{
40 struct nv50_bar *bar = nv50_bar(base);
41 return nvkm_vm_get(bar->bar1_vm, size, type, NV_MEM_ACCESS_RW, vma);
42}
43
44static void 31static void
45nv50_bar_flush(struct nvkm_bar *base) 32nv50_bar_flush(struct nvkm_bar *base)
46{ 33{
@@ -56,14 +43,72 @@ nv50_bar_flush(struct nvkm_bar *base)
56 spin_unlock_irqrestore(&bar->base.lock, flags); 43 spin_unlock_irqrestore(&bar->base.lock, flags);
57} 44}
58 45
46struct nvkm_vmm *
47nv50_bar_bar1_vmm(struct nvkm_bar *base)
48{
49 return nv50_bar(base)->bar1_vmm;
50}
51
52void
53nv50_bar_bar1_wait(struct nvkm_bar *base)
54{
55 nvkm_bar_flush(base);
56}
57
58void
59nv50_bar_bar1_fini(struct nvkm_bar *bar)
60{
61 nvkm_wr32(bar->subdev.device, 0x001708, 0x00000000);
62}
63
64void
65nv50_bar_bar1_init(struct nvkm_bar *base)
66{
67 struct nvkm_device *device = base->subdev.device;
68 struct nv50_bar *bar = nv50_bar(base);
69 nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4);
70}
71
72struct nvkm_vmm *
73nv50_bar_bar2_vmm(struct nvkm_bar *base)
74{
75 return nv50_bar(base)->bar2_vmm;
76}
77
78void
79nv50_bar_bar2_fini(struct nvkm_bar *bar)
80{
81 nvkm_wr32(bar->subdev.device, 0x00170c, 0x00000000);
82}
83
84void
85nv50_bar_bar2_init(struct nvkm_bar *base)
86{
87 struct nvkm_device *device = base->subdev.device;
88 struct nv50_bar *bar = nv50_bar(base);
89 nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12);
90 nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12);
91 nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar2->node->offset >> 4);
92}
93
94void
95nv50_bar_init(struct nvkm_bar *base)
96{
97 struct nv50_bar *bar = nv50_bar(base);
98 struct nvkm_device *device = bar->base.subdev.device;
99 int i;
100
101 for (i = 0; i < 8; i++)
102 nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000);
103}
104
59int 105int
60nv50_bar_oneinit(struct nvkm_bar *base) 106nv50_bar_oneinit(struct nvkm_bar *base)
61{ 107{
62 struct nv50_bar *bar = nv50_bar(base); 108 struct nv50_bar *bar = nv50_bar(base);
63 struct nvkm_device *device = bar->base.subdev.device; 109 struct nvkm_device *device = bar->base.subdev.device;
64 static struct lock_class_key bar1_lock; 110 static struct lock_class_key bar1_lock;
65 static struct lock_class_key bar3_lock; 111 static struct lock_class_key bar2_lock;
66 struct nvkm_vm *vm;
67 u64 start, limit; 112 u64 start, limit;
68 int ret; 113 int ret;
69 114
@@ -80,51 +125,54 @@ nv50_bar_oneinit(struct nvkm_bar *base)
80 if (ret) 125 if (ret)
81 return ret; 126 return ret;
82 127
83 /* BAR3 */ 128 /* BAR2 */
84 start = 0x0100000000ULL; 129 start = 0x0100000000ULL;
85 limit = start + device->func->resource_size(device, 3); 130 limit = start + device->func->resource_size(device, 3);
86 131
87 ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm); 132 ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
133 &bar2_lock, "bar2", &bar->bar2_vmm);
88 if (ret) 134 if (ret)
89 return ret; 135 return ret;
90 136
91 atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); 137 atomic_inc(&bar->bar2_vmm->engref[NVKM_SUBDEV_BAR]);
138 bar->bar2_vmm->debug = bar->base.subdev.debug;
92 139
93 ret = nvkm_vm_boot(vm, limit-- - start); 140 ret = nvkm_vmm_boot(bar->bar2_vmm);
94 if (ret) 141 if (ret)
95 return ret; 142 return ret;
96 143
97 ret = nvkm_vm_ref(vm, &bar->bar3_vm, bar->pgd); 144 ret = nvkm_vmm_join(bar->bar2_vmm, bar->mem->memory);
98 nvkm_vm_ref(NULL, &vm, NULL);
99 if (ret) 145 if (ret)
100 return ret; 146 return ret;
101 147
102 ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar3); 148 ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar2);
103 if (ret) 149 if (ret)
104 return ret; 150 return ret;
105 151
106 nvkm_kmap(bar->bar3); 152 nvkm_kmap(bar->bar2);
107 nvkm_wo32(bar->bar3, 0x00, 0x7fc00000); 153 nvkm_wo32(bar->bar2, 0x00, 0x7fc00000);
108 nvkm_wo32(bar->bar3, 0x04, lower_32_bits(limit)); 154 nvkm_wo32(bar->bar2, 0x04, lower_32_bits(limit));
109 nvkm_wo32(bar->bar3, 0x08, lower_32_bits(start)); 155 nvkm_wo32(bar->bar2, 0x08, lower_32_bits(start));
110 nvkm_wo32(bar->bar3, 0x0c, upper_32_bits(limit) << 24 | 156 nvkm_wo32(bar->bar2, 0x0c, upper_32_bits(limit) << 24 |
111 upper_32_bits(start)); 157 upper_32_bits(start));
112 nvkm_wo32(bar->bar3, 0x10, 0x00000000); 158 nvkm_wo32(bar->bar2, 0x10, 0x00000000);
113 nvkm_wo32(bar->bar3, 0x14, 0x00000000); 159 nvkm_wo32(bar->bar2, 0x14, 0x00000000);
114 nvkm_done(bar->bar3); 160 nvkm_done(bar->bar2);
161
162 bar->base.subdev.oneinit = true;
163 nvkm_bar_bar2_init(device);
115 164
116 /* BAR1 */ 165 /* BAR1 */
117 start = 0x0000000000ULL; 166 start = 0x0000000000ULL;
118 limit = start + device->func->resource_size(device, 1); 167 limit = start + device->func->resource_size(device, 1);
119 168
120 ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm); 169 ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
121 if (ret) 170 &bar1_lock, "bar1", &bar->bar1_vmm);
122 return ret;
123 171
124 atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); 172 atomic_inc(&bar->bar1_vmm->engref[NVKM_SUBDEV_BAR]);
173 bar->bar1_vmm->debug = bar->base.subdev.debug;
125 174
126 ret = nvkm_vm_ref(vm, &bar->bar1_vm, bar->pgd); 175 ret = nvkm_vmm_join(bar->bar1_vmm, bar->mem->memory);
127 nvkm_vm_ref(NULL, &vm, NULL);
128 if (ret) 176 if (ret)
129 return ret; 177 return ret;
130 178
@@ -144,45 +192,21 @@ nv50_bar_oneinit(struct nvkm_bar *base)
144 return 0; 192 return 0;
145} 193}
146 194
147int
148nv50_bar_init(struct nvkm_bar *base)
149{
150 struct nv50_bar *bar = nv50_bar(base);
151 struct nvkm_device *device = bar->base.subdev.device;
152 int i;
153
154 nvkm_mask(device, 0x000200, 0x00000100, 0x00000000);
155 nvkm_mask(device, 0x000200, 0x00000100, 0x00000100);
156 nvkm_wr32(device, 0x100c80, 0x00060001);
157 if (nvkm_msec(device, 2000,
158 if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
159 break;
160 ) < 0)
161 return -EBUSY;
162
163 nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12);
164 nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12);
165 nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4);
166 nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar3->node->offset >> 4);
167 for (i = 0; i < 8; i++)
168 nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000);
169 return 0;
170}
171
172void * 195void *
173nv50_bar_dtor(struct nvkm_bar *base) 196nv50_bar_dtor(struct nvkm_bar *base)
174{ 197{
175 struct nv50_bar *bar = nv50_bar(base); 198 struct nv50_bar *bar = nv50_bar(base);
176 nvkm_gpuobj_del(&bar->bar1); 199 if (bar->mem) {
177 nvkm_vm_ref(NULL, &bar->bar1_vm, bar->pgd); 200 nvkm_gpuobj_del(&bar->bar1);
178 nvkm_gpuobj_del(&bar->bar3); 201 nvkm_vmm_part(bar->bar1_vmm, bar->mem->memory);
179 if (bar->bar3_vm) { 202 nvkm_vmm_unref(&bar->bar1_vmm);
180 nvkm_memory_del(&bar->bar3_vm->pgt[0].mem[0]); 203 nvkm_gpuobj_del(&bar->bar2);
181 nvkm_vm_ref(NULL, &bar->bar3_vm, bar->pgd); 204 nvkm_vmm_part(bar->bar2_vmm, bar->mem->memory);
205 nvkm_vmm_unref(&bar->bar2_vmm);
206 nvkm_gpuobj_del(&bar->pgd);
207 nvkm_gpuobj_del(&bar->pad);
208 nvkm_gpuobj_del(&bar->mem);
182 } 209 }
183 nvkm_gpuobj_del(&bar->pgd);
184 nvkm_gpuobj_del(&bar->pad);
185 nvkm_gpuobj_del(&bar->mem);
186 return bar; 210 return bar;
187} 211}
188 212
@@ -204,8 +228,14 @@ nv50_bar_func = {
204 .dtor = nv50_bar_dtor, 228 .dtor = nv50_bar_dtor,
205 .oneinit = nv50_bar_oneinit, 229 .oneinit = nv50_bar_oneinit,
206 .init = nv50_bar_init, 230 .init = nv50_bar_init,
207 .kmap = nv50_bar_kmap, 231 .bar1.init = nv50_bar_bar1_init,
208 .umap = nv50_bar_umap, 232 .bar1.fini = nv50_bar_bar1_fini,
233 .bar1.wait = nv50_bar_bar1_wait,
234 .bar1.vmm = nv50_bar_bar1_vmm,
235 .bar2.init = nv50_bar_bar2_init,
236 .bar2.fini = nv50_bar_bar2_fini,
237 .bar2.wait = nv50_bar_bar1_wait,
238 .bar2.vmm = nv50_bar_bar2_vmm,
209 .flush = nv50_bar_flush, 239 .flush = nv50_bar_flush,
210}; 240};
211 241
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
index 1eb764f22a49..140b76f588b6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h
@@ -9,18 +9,20 @@ struct nv50_bar {
9 struct nvkm_gpuobj *mem; 9 struct nvkm_gpuobj *mem;
10 struct nvkm_gpuobj *pad; 10 struct nvkm_gpuobj *pad;
11 struct nvkm_gpuobj *pgd; 11 struct nvkm_gpuobj *pgd;
12 struct nvkm_vm *bar1_vm; 12 struct nvkm_vmm *bar1_vmm;
13 struct nvkm_gpuobj *bar1; 13 struct nvkm_gpuobj *bar1;
14 struct nvkm_vm *bar3_vm; 14 struct nvkm_vmm *bar2_vmm;
15 struct nvkm_gpuobj *bar3; 15 struct nvkm_gpuobj *bar2;
16}; 16};
17 17
18int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, 18int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *,
19 int, u32 pgd_addr, struct nvkm_bar **); 19 int, u32 pgd_addr, struct nvkm_bar **);
20void *nv50_bar_dtor(struct nvkm_bar *); 20void *nv50_bar_dtor(struct nvkm_bar *);
21int nv50_bar_oneinit(struct nvkm_bar *); 21int nv50_bar_oneinit(struct nvkm_bar *);
22int nv50_bar_init(struct nvkm_bar *); 22void nv50_bar_init(struct nvkm_bar *);
23struct nvkm_vm *nv50_bar_kmap(struct nvkm_bar *); 23void nv50_bar_bar1_init(struct nvkm_bar *);
24int nv50_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); 24void nv50_bar_bar1_wait(struct nvkm_bar *);
25void nv50_bar_unmap(struct nvkm_bar *, struct nvkm_vma *); 25struct nvkm_vmm *nv50_bar_bar1_vmm(struct nvkm_bar *);
26void nv50_bar_bar2_init(struct nvkm_bar *);
27struct nvkm_vmm *nv50_bar_bar2_vmm(struct nvkm_bar *);
26#endif 28#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
index d834ef20db5b..14398e2dbdf9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h
@@ -9,11 +9,25 @@ void nvkm_bar_ctor(const struct nvkm_bar_func *, struct nvkm_device *,
9struct nvkm_bar_func { 9struct nvkm_bar_func {
10 void *(*dtor)(struct nvkm_bar *); 10 void *(*dtor)(struct nvkm_bar *);
11 int (*oneinit)(struct nvkm_bar *); 11 int (*oneinit)(struct nvkm_bar *);
12 int (*init)(struct nvkm_bar *); 12 void (*init)(struct nvkm_bar *);
13 struct nvkm_vm *(*kmap)(struct nvkm_bar *); 13
14 int (*umap)(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); 14 struct {
15 void (*init)(struct nvkm_bar *);
16 void (*fini)(struct nvkm_bar *);
17 void (*wait)(struct nvkm_bar *);
18 struct nvkm_vmm *(*vmm)(struct nvkm_bar *);
19 } bar1, bar2;
20
15 void (*flush)(struct nvkm_bar *); 21 void (*flush)(struct nvkm_bar *);
16}; 22};
17 23
24void nv50_bar_bar1_fini(struct nvkm_bar *);
25void nv50_bar_bar2_fini(struct nvkm_bar *);
26
18void g84_bar_flush(struct nvkm_bar *); 27void g84_bar_flush(struct nvkm_bar *);
28
29void gf100_bar_bar1_fini(struct nvkm_bar *);
30void gf100_bar_bar2_fini(struct nvkm_bar *);
31
32void gm107_bar_bar1_wait(struct nvkm_bar *);
19#endif 33#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
index 23caef8df17f..73e463ed55c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
@@ -99,7 +99,7 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
99 rail->extdev_id = nvbios_rd08(bios, entry + 0x1); 99 rail->extdev_id = nvbios_rd08(bios, entry + 0x1);
100 res_start = 0x5; 100 res_start = 0x5;
101 break; 101 break;
102 }; 102 }
103 103
104 if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev)) 104 if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev))
105 continue; 105 continue;
@@ -115,7 +115,7 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
115 default: 115 default:
116 rail->resistor_count = 0; 116 rail->resistor_count = 0;
117 break; 117 break;
118 }; 118 }
119 119
120 for (r = 0; r < rail->resistor_count; ++r) { 120 for (r = 0; r < rail->resistor_count; ++r) {
121 rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2); 121 rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
index b58ee99f7bfc..9cc10e438b3d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
@@ -36,6 +36,8 @@
36#include <subdev/i2c.h> 36#include <subdev/i2c.h>
37#include <subdev/vga.h> 37#include <subdev/vga.h>
38 38
39#include <linux/kernel.h>
40
39#define bioslog(lvl, fmt, args...) do { \ 41#define bioslog(lvl, fmt, args...) do { \
40 nvkm_printk(init->subdev, lvl, info, "0x%08x[%c]: "fmt, \ 42 nvkm_printk(init->subdev, lvl, info, "0x%08x[%c]: "fmt, \
41 init->offset, init_exec(init) ? \ 43 init->offset, init_exec(init) ? \
@@ -2271,8 +2273,6 @@ static struct nvbios_init_opcode {
2271 [0xaa] = { init_reserved }, 2273 [0xaa] = { init_reserved },
2272}; 2274};
2273 2275
2274#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))
2275
2276int 2276int
2277nvbios_exec(struct nvbios_init *init) 2277nvbios_exec(struct nvbios_init *init)
2278{ 2278{
@@ -2281,7 +2281,8 @@ nvbios_exec(struct nvbios_init *init)
2281 init->nested++; 2281 init->nested++;
2282 while (init->offset) { 2282 while (init->offset) {
2283 u8 opcode = nvbios_rd08(bios, init->offset); 2283 u8 opcode = nvbios_rd08(bios, init->offset);
2284 if (opcode >= init_opcode_nr || !init_opcode[opcode].exec) { 2284 if (opcode >= ARRAY_SIZE(init_opcode) ||
2285 !init_opcode[opcode].exec) {
2285 error("unknown opcode 0x%02x\n", opcode); 2286 error("unknown opcode 0x%02x\n", opcode);
2286 return -EINVAL; 2287 return -EINVAL;
2287 } 2288 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
index a7049c041594..73b5d46104bd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
@@ -31,12 +31,6 @@
31#include <engine/gr.h> 31#include <engine/gr.h>
32#include <engine/mpeg.h> 32#include <engine/mpeg.h>
33 33
34bool
35nvkm_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype)
36{
37 return fb->func->memtype_valid(fb, memtype);
38}
39
40void 34void
41nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) 35nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile)
42{ 36{
@@ -100,6 +94,7 @@ static int
100nvkm_fb_oneinit(struct nvkm_subdev *subdev) 94nvkm_fb_oneinit(struct nvkm_subdev *subdev)
101{ 95{
102 struct nvkm_fb *fb = nvkm_fb(subdev); 96 struct nvkm_fb *fb = nvkm_fb(subdev);
97 u32 tags = 0;
103 98
104 if (fb->func->ram_new) { 99 if (fb->func->ram_new) {
105 int ret = fb->func->ram_new(fb, &fb->ram); 100 int ret = fb->func->ram_new(fb, &fb->ram);
@@ -115,7 +110,16 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev)
115 return ret; 110 return ret;
116 } 111 }
117 112
118 return 0; 113 /* Initialise compression tag allocator.
114 *
115 * LTC oneinit() will override this on Fermi and newer.
116 */
117 if (fb->func->tags) {
118 tags = fb->func->tags(fb);
119 nvkm_debug(subdev, "%d comptags\n", tags);
120 }
121
122 return nvkm_mm_init(&fb->tags, 0, 0, tags, 1);
119} 123}
120 124
121static int 125static int
@@ -135,8 +139,13 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
135 139
136 if (fb->func->init) 140 if (fb->func->init)
137 fb->func->init(fb); 141 fb->func->init(fb);
138 if (fb->func->init_page) 142
139 fb->func->init_page(fb); 143 if (fb->func->init_page) {
144 ret = fb->func->init_page(fb);
145 if (WARN_ON(ret))
146 return ret;
147 }
148
140 if (fb->func->init_unkn) 149 if (fb->func->init_unkn)
141 fb->func->init_unkn(fb); 150 fb->func->init_unkn(fb);
142 return 0; 151 return 0;
@@ -148,12 +157,13 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)
148 struct nvkm_fb *fb = nvkm_fb(subdev); 157 struct nvkm_fb *fb = nvkm_fb(subdev);
149 int i; 158 int i;
150 159
151 nvkm_memory_del(&fb->mmu_wr); 160 nvkm_memory_unref(&fb->mmu_wr);
152 nvkm_memory_del(&fb->mmu_rd); 161 nvkm_memory_unref(&fb->mmu_rd);
153 162
154 for (i = 0; i < fb->tile.regions; i++) 163 for (i = 0; i < fb->tile.regions; i++)
155 fb->func->tile.fini(fb, i, &fb->tile.region[i]); 164 fb->func->tile.fini(fb, i, &fb->tile.region[i]);
156 165
166 nvkm_mm_fini(&fb->tags);
157 nvkm_ram_del(&fb->ram); 167 nvkm_ram_del(&fb->ram);
158 168
159 if (fb->func->dtor) 169 if (fb->func->dtor)
@@ -176,7 +186,8 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
176 nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev); 186 nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev);
177 fb->func = func; 187 fb->func = func;
178 fb->tile.regions = fb->func->tile.regions; 188 fb->tile.regions = fb->func->tile.regions;
179 fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", 0); 189 fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage",
190 fb->func->default_bigpage);
180} 191}
181 192
182int 193int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c
index 9c28392d07e4..06bf95c0c549 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c
@@ -27,6 +27,7 @@
27static const struct nv50_fb_func 27static const struct nv50_fb_func
28g84_fb = { 28g84_fb = {
29 .ram_new = nv50_ram_new, 29 .ram_new = nv50_ram_new,
30 .tags = nv20_fb_tags,
30 .trap = 0x001d07ff, 31 .trap = 0x001d07ff,
31}; 32};
32 33
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
index a239e73562c8..47d28c279707 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
@@ -27,15 +27,6 @@
27#include <core/memory.h> 27#include <core/memory.h>
28#include <core/option.h> 28#include <core/option.h>
29 29
30extern const u8 gf100_pte_storage_type_map[256];
31
32bool
33gf100_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags)
34{
35 u8 memtype = (tile_flags & 0x0000ff00) >> 8;
36 return likely((gf100_pte_storage_type_map[memtype] != 0xff));
37}
38
39void 30void
40gf100_fb_intr(struct nvkm_fb *base) 31gf100_fb_intr(struct nvkm_fb *base)
41{ 32{
@@ -80,20 +71,17 @@ gf100_fb_oneinit(struct nvkm_fb *base)
80 return 0; 71 return 0;
81} 72}
82 73
83void 74int
84gf100_fb_init_page(struct nvkm_fb *fb) 75gf100_fb_init_page(struct nvkm_fb *fb)
85{ 76{
86 struct nvkm_device *device = fb->subdev.device; 77 struct nvkm_device *device = fb->subdev.device;
87 switch (fb->page) { 78 switch (fb->page) {
88 case 16: 79 case 16: nvkm_mask(device, 0x100c80, 0x00000001, 0x00000001); break;
89 nvkm_mask(device, 0x100c80, 0x00000001, 0x00000001); 80 case 17: nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); break;
90 break;
91 case 17:
92 default: 81 default:
93 nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); 82 return -EINVAL;
94 fb->page = 17;
95 break;
96 } 83 }
84 return 0;
97} 85}
98 86
99void 87void
@@ -143,7 +131,7 @@ gf100_fb = {
143 .init_page = gf100_fb_init_page, 131 .init_page = gf100_fb_init_page,
144 .intr = gf100_fb_intr, 132 .intr = gf100_fb_intr,
145 .ram_new = gf100_ram_new, 133 .ram_new = gf100_ram_new,
146 .memtype_valid = gf100_fb_memtype_valid, 134 .default_bigpage = 17,
147}; 135};
148 136
149int 137int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
index 412eb89834e8..e3cf0515bb70 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
@@ -17,7 +17,5 @@ void gf100_fb_intr(struct nvkm_fb *);
17 17
18void gp100_fb_init(struct nvkm_fb *); 18void gp100_fb_init(struct nvkm_fb *);
19 19
20void gm200_fb_init_page(struct nvkm_fb *fb);
21void gm200_fb_init(struct nvkm_fb *base); 20void gm200_fb_init(struct nvkm_fb *base);
22
23#endif 21#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c
index 56af84aa333b..4a9f463745b5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c
@@ -32,7 +32,7 @@ gf108_fb = {
32 .init_page = gf100_fb_init_page, 32 .init_page = gf100_fb_init_page,
33 .intr = gf100_fb_intr, 33 .intr = gf100_fb_intr,
34 .ram_new = gf108_ram_new, 34 .ram_new = gf108_ram_new,
35 .memtype_valid = gf100_fb_memtype_valid, 35 .default_bigpage = 17,
36}; 36};
37 37
38int 38int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
index 4245e2e6e604..0a6e8eaad42c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
@@ -32,7 +32,7 @@ gk104_fb = {
32 .init_page = gf100_fb_init_page, 32 .init_page = gf100_fb_init_page,
33 .intr = gf100_fb_intr, 33 .intr = gf100_fb_intr,
34 .ram_new = gk104_ram_new, 34 .ram_new = gk104_ram_new,
35 .memtype_valid = gf100_fb_memtype_valid, 35 .default_bigpage = 17,
36}; 36};
37 37
38int 38int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
index 5d34d6136616..a7e29b125094 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
@@ -30,7 +30,7 @@ gk20a_fb = {
30 .init = gf100_fb_init, 30 .init = gf100_fb_init,
31 .init_page = gf100_fb_init_page, 31 .init_page = gf100_fb_init_page,
32 .intr = gf100_fb_intr, 32 .intr = gf100_fb_intr,
33 .memtype_valid = gf100_fb_memtype_valid, 33 .default_bigpage = 17,
34}; 34};
35 35
36int 36int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
index db699025f546..69c876d5d1c1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
@@ -32,7 +32,7 @@ gm107_fb = {
32 .init_page = gf100_fb_init_page, 32 .init_page = gf100_fb_init_page,
33 .intr = gf100_fb_intr, 33 .intr = gf100_fb_intr,
34 .ram_new = gm107_ram_new, 34 .ram_new = gm107_ram_new,
35 .memtype_valid = gf100_fb_memtype_valid, 35 .default_bigpage = 17,
36}; 36};
37 37
38int 38int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
index d83da5ddbc1e..8137e19d3292 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
@@ -26,22 +26,18 @@
26 26
27#include <core/memory.h> 27#include <core/memory.h>
28 28
29void 29int
30gm200_fb_init_page(struct nvkm_fb *fb) 30gm200_fb_init_page(struct nvkm_fb *fb)
31{ 31{
32 struct nvkm_device *device = fb->subdev.device; 32 struct nvkm_device *device = fb->subdev.device;
33 switch (fb->page) { 33 switch (fb->page) {
34 case 16: 34 case 16: nvkm_mask(device, 0x100c80, 0x00001801, 0x00001001); break;
35 nvkm_mask(device, 0x100c80, 0x00000801, 0x00000001); 35 case 17: nvkm_mask(device, 0x100c80, 0x00001801, 0x00000000); break;
36 break; 36 case 0: nvkm_mask(device, 0x100c80, 0x00001800, 0x00001800); break;
37 case 17:
38 nvkm_mask(device, 0x100c80, 0x00000801, 0x00000000);
39 break;
40 default: 37 default:
41 nvkm_mask(device, 0x100c80, 0x00000800, 0x00000800); 38 return -EINVAL;
42 fb->page = 0;
43 break;
44 } 39 }
40 return 0;
45} 41}
46 42
47void 43void
@@ -69,7 +65,7 @@ gm200_fb = {
69 .init_page = gm200_fb_init_page, 65 .init_page = gm200_fb_init_page,
70 .intr = gf100_fb_intr, 66 .intr = gf100_fb_intr,
71 .ram_new = gm200_ram_new, 67 .ram_new = gm200_ram_new,
72 .memtype_valid = gf100_fb_memtype_valid, 68 .default_bigpage = 0 /* per-instance. */,
73}; 69};
74 70
75int 71int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
index b87c233bcd6d..12db61e31128 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
@@ -30,7 +30,7 @@ gm20b_fb = {
30 .init = gm200_fb_init, 30 .init = gm200_fb_init,
31 .init_page = gm200_fb_init_page, 31 .init_page = gm200_fb_init_page,
32 .intr = gf100_fb_intr, 32 .intr = gf100_fb_intr,
33 .memtype_valid = gf100_fb_memtype_valid, 33 .default_bigpage = 0 /* per-instance. */,
34}; 34};
35 35
36int 36int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
index 98474aec1921..147f69b30cd8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
@@ -59,7 +59,6 @@ gp100_fb = {
59 .init_page = gm200_fb_init_page, 59 .init_page = gm200_fb_init_page,
60 .init_unkn = gp100_fb_init_unkn, 60 .init_unkn = gp100_fb_init_unkn,
61 .ram_new = gp100_ram_new, 61 .ram_new = gp100_ram_new,
62 .memtype_valid = gf100_fb_memtype_valid,
63}; 62};
64 63
65int 64int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
index 73b4ae1c73dc..b84b9861ef26 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
@@ -33,7 +33,6 @@ gp102_fb = {
33 .init = gp100_fb_init, 33 .init = gp100_fb_init,
34 .init_page = gm200_fb_init_page, 34 .init_page = gm200_fb_init_page,
35 .ram_new = gp100_ram_new, 35 .ram_new = gp100_ram_new,
36 .memtype_valid = gf100_fb_memtype_valid,
37}; 36};
38 37
39int 38int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
index f2b1fbf428d5..af8e43979dc1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
@@ -28,7 +28,6 @@ gp10b_fb = {
28 .init = gm200_fb_init, 28 .init = gm200_fb_init,
29 .init_page = gm200_fb_init_page, 29 .init_page = gm200_fb_init_page,
30 .intr = gf100_fb_intr, 30 .intr = gf100_fb_intr,
31 .memtype_valid = gf100_fb_memtype_valid,
32}; 31};
33 32
34int 33int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c
index ebb30608d5ef..9266559b45f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c
@@ -27,6 +27,7 @@
27static const struct nv50_fb_func 27static const struct nv50_fb_func
28gt215_fb = { 28gt215_fb = {
29 .ram_new = gt215_ram_new, 29 .ram_new = gt215_ram_new,
30 .tags = nv20_fb_tags,
30 .trap = 0x000d0fff, 31 .trap = 0x000d0fff,
31}; 32};
32 33
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c
index 8ff2e5db4571..c886664533c8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c
@@ -25,14 +25,6 @@
25#include "ram.h" 25#include "ram.h"
26#include "regsnv04.h" 26#include "regsnv04.h"
27 27
28bool
29nv04_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags)
30{
31 if (!(tile_flags & 0xff00))
32 return true;
33 return false;
34}
35
36static void 28static void
37nv04_fb_init(struct nvkm_fb *fb) 29nv04_fb_init(struct nvkm_fb *fb)
38{ 30{
@@ -49,7 +41,6 @@ static const struct nvkm_fb_func
49nv04_fb = { 41nv04_fb = {
50 .init = nv04_fb_init, 42 .init = nv04_fb_init,
51 .ram_new = nv04_ram_new, 43 .ram_new = nv04_ram_new,
52 .memtype_valid = nv04_fb_memtype_valid,
53}; 44};
54 45
55int 46int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c
index e8c44f5a3d84..c998b7e96aa3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c
@@ -61,7 +61,6 @@ nv10_fb = {
61 .tile.fini = nv10_fb_tile_fini, 61 .tile.fini = nv10_fb_tile_fini,
62 .tile.prog = nv10_fb_tile_prog, 62 .tile.prog = nv10_fb_tile_prog,
63 .ram_new = nv10_ram_new, 63 .ram_new = nv10_ram_new,
64 .memtype_valid = nv04_fb_memtype_valid,
65}; 64};
66 65
67int 66int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c
index 2ae0beb87567..7b9f04f44af8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c
@@ -33,7 +33,6 @@ nv1a_fb = {
33 .tile.fini = nv10_fb_tile_fini, 33 .tile.fini = nv10_fb_tile_fini,
34 .tile.prog = nv10_fb_tile_prog, 34 .tile.prog = nv10_fb_tile_prog,
35 .ram_new = nv1a_ram_new, 35 .ram_new = nv1a_ram_new,
36 .memtype_valid = nv04_fb_memtype_valid,
37}; 36};
38 37
39int 38int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c
index 126865dfe777..a021d21ff153 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c
@@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
45{ 45{
46 u32 tiles = DIV_ROUND_UP(size, 0x40); 46 u32 tiles = DIV_ROUND_UP(size, 0x40);
47 u32 tags = round_up(tiles / fb->ram->parts, 0x40); 47 u32 tags = round_up(tiles / fb->ram->parts, 0x40);
48 if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 48 if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
49 if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */ 49 if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */
50 else tile->zcomp = 0x04000000; /* Z24S8 */ 50 else tile->zcomp = 0x04000000; /* Z24S8 */
51 tile->zcomp |= tile->tag->offset; 51 tile->zcomp |= tile->tag->offset;
@@ -63,7 +63,7 @@ nv20_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile)
63 tile->limit = 0; 63 tile->limit = 0;
64 tile->pitch = 0; 64 tile->pitch = 0;
65 tile->zcomp = 0; 65 tile->zcomp = 0;
66 nvkm_mm_free(&fb->ram->tags, &tile->tag); 66 nvkm_mm_free(&fb->tags, &tile->tag);
67} 67}
68 68
69void 69void
@@ -77,15 +77,22 @@ nv20_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile)
77 nvkm_wr32(device, 0x100300 + (i * 0x04), tile->zcomp); 77 nvkm_wr32(device, 0x100300 + (i * 0x04), tile->zcomp);
78} 78}
79 79
80u32
81nv20_fb_tags(struct nvkm_fb *fb)
82{
83 const u32 tags = nvkm_rd32(fb->subdev.device, 0x100320);
84 return tags ? tags + 1 : 0;
85}
86
80static const struct nvkm_fb_func 87static const struct nvkm_fb_func
81nv20_fb = { 88nv20_fb = {
89 .tags = nv20_fb_tags,
82 .tile.regions = 8, 90 .tile.regions = 8,
83 .tile.init = nv20_fb_tile_init, 91 .tile.init = nv20_fb_tile_init,
84 .tile.comp = nv20_fb_tile_comp, 92 .tile.comp = nv20_fb_tile_comp,
85 .tile.fini = nv20_fb_tile_fini, 93 .tile.fini = nv20_fb_tile_fini,
86 .tile.prog = nv20_fb_tile_prog, 94 .tile.prog = nv20_fb_tile_prog,
87 .ram_new = nv20_ram_new, 95 .ram_new = nv20_ram_new,
88 .memtype_valid = nv04_fb_memtype_valid,
89}; 96};
90 97
91int 98int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c
index c56746d2a502..7709f5fe9a45 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c
@@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
32{ 32{
33 u32 tiles = DIV_ROUND_UP(size, 0x40); 33 u32 tiles = DIV_ROUND_UP(size, 0x40);
34 u32 tags = round_up(tiles / fb->ram->parts, 0x40); 34 u32 tags = round_up(tiles / fb->ram->parts, 0x40);
35 if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 35 if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
36 if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */ 36 if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */
37 else tile->zcomp = 0x00200000; /* Z24S8 */ 37 else tile->zcomp = 0x00200000; /* Z24S8 */
38 tile->zcomp |= tile->tag->offset; 38 tile->zcomp |= tile->tag->offset;
@@ -44,13 +44,13 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
44 44
45static const struct nvkm_fb_func 45static const struct nvkm_fb_func
46nv25_fb = { 46nv25_fb = {
47 .tags = nv20_fb_tags,
47 .tile.regions = 8, 48 .tile.regions = 8,
48 .tile.init = nv20_fb_tile_init, 49 .tile.init = nv20_fb_tile_init,
49 .tile.comp = nv25_fb_tile_comp, 50 .tile.comp = nv25_fb_tile_comp,
50 .tile.fini = nv20_fb_tile_fini, 51 .tile.fini = nv20_fb_tile_fini,
51 .tile.prog = nv20_fb_tile_prog, 52 .tile.prog = nv20_fb_tile_prog,
52 .ram_new = nv20_ram_new, 53 .ram_new = nv20_ram_new,
53 .memtype_valid = nv04_fb_memtype_valid,
54}; 54};
55 55
56int 56int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c
index 2a7c4831b821..8aa782666507 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c
@@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
51{ 51{
52 u32 tiles = DIV_ROUND_UP(size, 0x40); 52 u32 tiles = DIV_ROUND_UP(size, 0x40);
53 u32 tags = round_up(tiles / fb->ram->parts, 0x40); 53 u32 tags = round_up(tiles / fb->ram->parts, 0x40);
54 if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 54 if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
55 if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */ 55 if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */
56 else tile->zcomp |= 0x02000000; /* Z24S8 */ 56 else tile->zcomp |= 0x02000000; /* Z24S8 */
57 tile->zcomp |= ((tile->tag->offset ) >> 6); 57 tile->zcomp |= ((tile->tag->offset ) >> 6);
@@ -116,6 +116,7 @@ nv30_fb_init(struct nvkm_fb *fb)
116 116
117static const struct nvkm_fb_func 117static const struct nvkm_fb_func
118nv30_fb = { 118nv30_fb = {
119 .tags = nv20_fb_tags,
119 .init = nv30_fb_init, 120 .init = nv30_fb_init,
120 .tile.regions = 8, 121 .tile.regions = 8,
121 .tile.init = nv30_fb_tile_init, 122 .tile.init = nv30_fb_tile_init,
@@ -123,7 +124,6 @@ nv30_fb = {
123 .tile.fini = nv20_fb_tile_fini, 124 .tile.fini = nv20_fb_tile_fini,
124 .tile.prog = nv20_fb_tile_prog, 125 .tile.prog = nv20_fb_tile_prog,
125 .ram_new = nv20_ram_new, 126 .ram_new = nv20_ram_new,
126 .memtype_valid = nv04_fb_memtype_valid,
127}; 127};
128 128
129int 129int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c
index 1604b3789ad1..6e83dcff72e0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c
@@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
32{ 32{
33 u32 tiles = DIV_ROUND_UP(size, 0x40); 33 u32 tiles = DIV_ROUND_UP(size, 0x40);
34 u32 tags = round_up(tiles / fb->ram->parts, 0x40); 34 u32 tags = round_up(tiles / fb->ram->parts, 0x40);
35 if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 35 if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
36 if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */ 36 if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */
37 else tile->zcomp |= 0x08000000; /* Z24S8 */ 37 else tile->zcomp |= 0x08000000; /* Z24S8 */
38 tile->zcomp |= ((tile->tag->offset ) >> 6); 38 tile->zcomp |= ((tile->tag->offset ) >> 6);
@@ -45,6 +45,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
45 45
46static const struct nvkm_fb_func 46static const struct nvkm_fb_func
47nv35_fb = { 47nv35_fb = {
48 .tags = nv20_fb_tags,
48 .init = nv30_fb_init, 49 .init = nv30_fb_init,
49 .tile.regions = 8, 50 .tile.regions = 8,
50 .tile.init = nv30_fb_tile_init, 51 .tile.init = nv30_fb_tile_init,
@@ -52,7 +53,6 @@ nv35_fb = {
52 .tile.fini = nv20_fb_tile_fini, 53 .tile.fini = nv20_fb_tile_fini,
53 .tile.prog = nv20_fb_tile_prog, 54 .tile.prog = nv20_fb_tile_prog,
54 .ram_new = nv20_ram_new, 55 .ram_new = nv20_ram_new,
55 .memtype_valid = nv04_fb_memtype_valid,
56}; 56};
57 57
58int 58int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c
index 80cc0a6e3416..2a07617bb44c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c
@@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
32{ 32{
33 u32 tiles = DIV_ROUND_UP(size, 0x40); 33 u32 tiles = DIV_ROUND_UP(size, 0x40);
34 u32 tags = round_up(tiles / fb->ram->parts, 0x40); 34 u32 tags = round_up(tiles / fb->ram->parts, 0x40);
35 if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 35 if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
36 if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */ 36 if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */
37 else tile->zcomp |= 0x20000000; /* Z24S8 */ 37 else tile->zcomp |= 0x20000000; /* Z24S8 */
38 tile->zcomp |= ((tile->tag->offset ) >> 6); 38 tile->zcomp |= ((tile->tag->offset ) >> 6);
@@ -45,6 +45,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
45 45
46static const struct nvkm_fb_func 46static const struct nvkm_fb_func
47nv36_fb = { 47nv36_fb = {
48 .tags = nv20_fb_tags,
48 .init = nv30_fb_init, 49 .init = nv30_fb_init,
49 .tile.regions = 8, 50 .tile.regions = 8,
50 .tile.init = nv30_fb_tile_init, 51 .tile.init = nv30_fb_tile_init,
@@ -52,7 +53,6 @@ nv36_fb = {
52 .tile.fini = nv20_fb_tile_fini, 53 .tile.fini = nv20_fb_tile_fini,
53 .tile.prog = nv20_fb_tile_prog, 54 .tile.prog = nv20_fb_tile_prog,
54 .ram_new = nv20_ram_new, 55 .ram_new = nv20_ram_new,
55 .memtype_valid = nv04_fb_memtype_valid,
56}; 56};
57 57
58int 58int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c
index deec46a310f8..955160778b5b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c
@@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags,
33 u32 tiles = DIV_ROUND_UP(size, 0x80); 33 u32 tiles = DIV_ROUND_UP(size, 0x80);
34 u32 tags = round_up(tiles / fb->ram->parts, 0x100); 34 u32 tags = round_up(tiles / fb->ram->parts, 0x100);
35 if ( (flags & 2) && 35 if ( (flags & 2) &&
36 !nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { 36 !nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) {
37 tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */ 37 tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */
38 tile->zcomp |= ((tile->tag->offset ) >> 8); 38 tile->zcomp |= ((tile->tag->offset ) >> 8);
39 tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13; 39 tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13;
@@ -51,6 +51,7 @@ nv40_fb_init(struct nvkm_fb *fb)
51 51
52static const struct nvkm_fb_func 52static const struct nvkm_fb_func
53nv40_fb = { 53nv40_fb = {
54 .tags = nv20_fb_tags,
54 .init = nv40_fb_init, 55 .init = nv40_fb_init,
55 .tile.regions = 8, 56 .tile.regions = 8,
56 .tile.init = nv30_fb_tile_init, 57 .tile.init = nv30_fb_tile_init,
@@ -58,7 +59,6 @@ nv40_fb = {
58 .tile.fini = nv20_fb_tile_fini, 59 .tile.fini = nv20_fb_tile_fini,
59 .tile.prog = nv20_fb_tile_prog, 60 .tile.prog = nv20_fb_tile_prog,
60 .ram_new = nv40_ram_new, 61 .ram_new = nv40_ram_new,
61 .memtype_valid = nv04_fb_memtype_valid,
62}; 62};
63 63
64int 64int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c
index 79e57dd5a00f..b77f08d34cc3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c
@@ -45,6 +45,7 @@ nv41_fb_init(struct nvkm_fb *fb)
45 45
46static const struct nvkm_fb_func 46static const struct nvkm_fb_func
47nv41_fb = { 47nv41_fb = {
48 .tags = nv20_fb_tags,
48 .init = nv41_fb_init, 49 .init = nv41_fb_init,
49 .tile.regions = 12, 50 .tile.regions = 12,
50 .tile.init = nv30_fb_tile_init, 51 .tile.init = nv30_fb_tile_init,
@@ -52,7 +53,6 @@ nv41_fb = {
52 .tile.fini = nv20_fb_tile_fini, 53 .tile.fini = nv20_fb_tile_fini,
53 .tile.prog = nv41_fb_tile_prog, 54 .tile.prog = nv41_fb_tile_prog,
54 .ram_new = nv41_ram_new, 55 .ram_new = nv41_ram_new,
55 .memtype_valid = nv04_fb_memtype_valid,
56}; 56};
57 57
58int 58int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c
index 06246cce5ec4..b59dc486083d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c
@@ -62,7 +62,6 @@ nv44_fb = {
62 .tile.fini = nv20_fb_tile_fini, 62 .tile.fini = nv20_fb_tile_fini,
63 .tile.prog = nv44_fb_tile_prog, 63 .tile.prog = nv44_fb_tile_prog,
64 .ram_new = nv44_ram_new, 64 .ram_new = nv44_ram_new,
65 .memtype_valid = nv04_fb_memtype_valid,
66}; 65};
67 66
68int 67int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c
index 3598a1aa65be..cab7d20fa039 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c
@@ -48,7 +48,6 @@ nv46_fb = {
48 .tile.fini = nv20_fb_tile_fini, 48 .tile.fini = nv20_fb_tile_fini,
49 .tile.prog = nv44_fb_tile_prog, 49 .tile.prog = nv44_fb_tile_prog,
50 .ram_new = nv44_ram_new, 50 .ram_new = nv44_ram_new,
51 .memtype_valid = nv04_fb_memtype_valid,
52}; 51};
53 52
54int 53int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c
index c505e4429314..a8b0ad4c871d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c
@@ -28,6 +28,7 @@
28 28
29static const struct nvkm_fb_func 29static const struct nvkm_fb_func
30nv47_fb = { 30nv47_fb = {
31 .tags = nv20_fb_tags,
31 .init = nv41_fb_init, 32 .init = nv41_fb_init,
32 .tile.regions = 15, 33 .tile.regions = 15,
33 .tile.init = nv30_fb_tile_init, 34 .tile.init = nv30_fb_tile_init,
@@ -35,7 +36,6 @@ nv47_fb = {
35 .tile.fini = nv20_fb_tile_fini, 36 .tile.fini = nv20_fb_tile_fini,
36 .tile.prog = nv41_fb_tile_prog, 37 .tile.prog = nv41_fb_tile_prog,
37 .ram_new = nv41_ram_new, 38 .ram_new = nv41_ram_new,
38 .memtype_valid = nv04_fb_memtype_valid,
39}; 39};
40 40
41int 41int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c
index 7b91b9f170e5..d0b317bb0252 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c
@@ -28,6 +28,7 @@
28 28
29static const struct nvkm_fb_func 29static const struct nvkm_fb_func
30nv49_fb = { 30nv49_fb = {
31 .tags = nv20_fb_tags,
31 .init = nv41_fb_init, 32 .init = nv41_fb_init,
32 .tile.regions = 15, 33 .tile.regions = 15,
33 .tile.init = nv30_fb_tile_init, 34 .tile.init = nv30_fb_tile_init,
@@ -35,7 +36,6 @@ nv49_fb = {
35 .tile.fini = nv20_fb_tile_fini, 36 .tile.fini = nv20_fb_tile_fini,
36 .tile.prog = nv41_fb_tile_prog, 37 .tile.prog = nv41_fb_tile_prog,
37 .ram_new = nv49_ram_new, 38 .ram_new = nv49_ram_new,
38 .memtype_valid = nv04_fb_memtype_valid,
39}; 39};
40 40
41int 41int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c
index 4e98210c1b1c..6a6f0c086071 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c
@@ -34,7 +34,6 @@ nv4e_fb = {
34 .tile.fini = nv20_fb_tile_fini, 34 .tile.fini = nv20_fb_tile_fini,
35 .tile.prog = nv44_fb_tile_prog, 35 .tile.prog = nv44_fb_tile_prog,
36 .ram_new = nv44_ram_new, 36 .ram_new = nv44_ram_new,
37 .memtype_valid = nv04_fb_memtype_valid,
38}; 37};
39 38
40int 39int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
index 0595e0722bfc..b2f5bf8144ea 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
@@ -28,18 +28,6 @@
28#include <core/enum.h> 28#include <core/enum.h>
29#include <engine/fifo.h> 29#include <engine/fifo.h>
30 30
31int
32nv50_fb_memtype[0x80] = {
33 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0,
35 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0,
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0,
38 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2,
40 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0
41};
42
43static int 31static int
44nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram) 32nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram)
45{ 33{
@@ -47,12 +35,6 @@ nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram)
47 return fb->func->ram_new(&fb->base, pram); 35 return fb->func->ram_new(&fb->base, pram);
48} 36}
49 37
50static bool
51nv50_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype)
52{
53 return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0;
54}
55
56static const struct nvkm_enum vm_dispatch_subclients[] = { 38static const struct nvkm_enum vm_dispatch_subclients[] = {
57 { 0x00000000, "GRCTX" }, 39 { 0x00000000, "GRCTX" },
58 { 0x00000001, "NOTIFY" }, 40 { 0x00000001, "NOTIFY" },
@@ -244,6 +226,15 @@ nv50_fb_init(struct nvkm_fb *base)
244 nvkm_wr32(device, 0x100c90, fb->func->trap); 226 nvkm_wr32(device, 0x100c90, fb->func->trap);
245} 227}
246 228
229static u32
230nv50_fb_tags(struct nvkm_fb *base)
231{
232 struct nv50_fb *fb = nv50_fb(base);
233 if (fb->func->tags)
234 return fb->func->tags(&fb->base);
235 return 0;
236}
237
247static void * 238static void *
248nv50_fb_dtor(struct nvkm_fb *base) 239nv50_fb_dtor(struct nvkm_fb *base)
249{ 240{
@@ -262,11 +253,11 @@ nv50_fb_dtor(struct nvkm_fb *base)
262static const struct nvkm_fb_func 253static const struct nvkm_fb_func
263nv50_fb_ = { 254nv50_fb_ = {
264 .dtor = nv50_fb_dtor, 255 .dtor = nv50_fb_dtor,
256 .tags = nv50_fb_tags,
265 .oneinit = nv50_fb_oneinit, 257 .oneinit = nv50_fb_oneinit,
266 .init = nv50_fb_init, 258 .init = nv50_fb_init,
267 .intr = nv50_fb_intr, 259 .intr = nv50_fb_intr,
268 .ram_new = nv50_fb_ram_new, 260 .ram_new = nv50_fb_ram_new,
269 .memtype_valid = nv50_fb_memtype_valid,
270}; 261};
271 262
272int 263int
@@ -287,6 +278,7 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device,
287static const struct nv50_fb_func 278static const struct nv50_fb_func
288nv50_fb = { 279nv50_fb = {
289 .ram_new = nv50_ram_new, 280 .ram_new = nv50_ram_new,
281 .tags = nv20_fb_tags,
290 .trap = 0x000707ff, 282 .trap = 0x000707ff,
291}; 283};
292 284
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
index faa88c8c66fe..13231d4b00d9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
@@ -12,10 +12,10 @@ struct nv50_fb {
12 12
13struct nv50_fb_func { 13struct nv50_fb_func {
14 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); 14 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **);
15 u32 (*tags)(struct nvkm_fb *);
15 u32 trap; 16 u32 trap;
16}; 17};
17 18
18int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index, 19int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index,
19 struct nvkm_fb **pfb); 20 struct nvkm_fb **pfb);
20extern int nv50_fb_memtype[0x80];
21#endif 21#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
index e905d44fa1d5..e05d95240e85 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
@@ -6,9 +6,10 @@ struct nvkm_bios;
6 6
7struct nvkm_fb_func { 7struct nvkm_fb_func {
8 void *(*dtor)(struct nvkm_fb *); 8 void *(*dtor)(struct nvkm_fb *);
9 u32 (*tags)(struct nvkm_fb *);
9 int (*oneinit)(struct nvkm_fb *); 10 int (*oneinit)(struct nvkm_fb *);
10 void (*init)(struct nvkm_fb *); 11 void (*init)(struct nvkm_fb *);
11 void (*init_page)(struct nvkm_fb *); 12 int (*init_page)(struct nvkm_fb *);
12 void (*init_unkn)(struct nvkm_fb *); 13 void (*init_unkn)(struct nvkm_fb *);
13 void (*intr)(struct nvkm_fb *); 14 void (*intr)(struct nvkm_fb *);
14 15
@@ -24,7 +25,7 @@ struct nvkm_fb_func {
24 25
25 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); 26 int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **);
26 27
27 bool (*memtype_valid)(struct nvkm_fb *, u32 memtype); 28 u8 default_bigpage;
28}; 29};
29 30
30void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, 31void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device,
@@ -33,13 +34,12 @@ int nvkm_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *device,
33 int index, struct nvkm_fb **); 34 int index, struct nvkm_fb **);
34int nvkm_fb_bios_memtype(struct nvkm_bios *); 35int nvkm_fb_bios_memtype(struct nvkm_bios *);
35 36
36bool nv04_fb_memtype_valid(struct nvkm_fb *, u32 memtype);
37
38void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, 37void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
39 u32 pitch, u32 flags, struct nvkm_fb_tile *); 38 u32 pitch, u32 flags, struct nvkm_fb_tile *);
40void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); 39void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *);
41void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); 40void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *);
42 41
42u32 nv20_fb_tags(struct nvkm_fb *);
43void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, 43void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
44 u32 pitch, u32 flags, struct nvkm_fb_tile *); 44 u32 pitch, u32 flags, struct nvkm_fb_tile *);
45void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); 45void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *);
@@ -62,8 +62,7 @@ void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
62 u32 pitch, u32 flags, struct nvkm_fb_tile *); 62 u32 pitch, u32 flags, struct nvkm_fb_tile *);
63 63
64int gf100_fb_oneinit(struct nvkm_fb *); 64int gf100_fb_oneinit(struct nvkm_fb *);
65void gf100_fb_init_page(struct nvkm_fb *); 65int gf100_fb_init_page(struct nvkm_fb *);
66bool gf100_fb_memtype_valid(struct nvkm_fb *, u32);
67 66
68void gm200_fb_init_page(struct nvkm_fb *); 67int gm200_fb_init_page(struct nvkm_fb *);
69#endif 68#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
index c17d559dbfbe..24c7bd505731 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
@@ -21,8 +21,132 @@
21 * 21 *
22 * Authors: Ben Skeggs <bskeggs@redhat.com> 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
23 */ 23 */
24#define nvkm_vram(p) container_of((p), struct nvkm_vram, memory)
24#include "ram.h" 25#include "ram.h"
25 26
27#include <core/memory.h>
28#include <subdev/mmu.h>
29
30struct nvkm_vram {
31 struct nvkm_memory memory;
32 struct nvkm_ram *ram;
33 u8 page;
34 struct nvkm_mm_node *mn;
35};
36
37static int
38nvkm_vram_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
39 struct nvkm_vma *vma, void *argv, u32 argc)
40{
41 struct nvkm_vram *vram = nvkm_vram(memory);
42 struct nvkm_vmm_map map = {
43 .memory = &vram->memory,
44 .offset = offset,
45 .mem = vram->mn,
46 };
47
48 return nvkm_vmm_map(vmm, vma, argv, argc, &map);
49}
50
51static u64
52nvkm_vram_size(struct nvkm_memory *memory)
53{
54 return (u64)nvkm_mm_size(nvkm_vram(memory)->mn) << NVKM_RAM_MM_SHIFT;
55}
56
57static u64
58nvkm_vram_addr(struct nvkm_memory *memory)
59{
60 struct nvkm_vram *vram = nvkm_vram(memory);
61 if (!nvkm_mm_contiguous(vram->mn))
62 return ~0ULL;
63 return (u64)nvkm_mm_addr(vram->mn) << NVKM_RAM_MM_SHIFT;
64}
65
66static u8
67nvkm_vram_page(struct nvkm_memory *memory)
68{
69 return nvkm_vram(memory)->page;
70}
71
72static enum nvkm_memory_target
73nvkm_vram_target(struct nvkm_memory *memory)
74{
75 return NVKM_MEM_TARGET_VRAM;
76}
77
78static void *
79nvkm_vram_dtor(struct nvkm_memory *memory)
80{
81 struct nvkm_vram *vram = nvkm_vram(memory);
82 struct nvkm_mm_node *next = vram->mn;
83 struct nvkm_mm_node *node;
84 mutex_lock(&vram->ram->fb->subdev.mutex);
85 while ((node = next)) {
86 next = node->next;
87 nvkm_mm_free(&vram->ram->vram, &node);
88 }
89 mutex_unlock(&vram->ram->fb->subdev.mutex);
90 return vram;
91}
92
93static const struct nvkm_memory_func
94nvkm_vram = {
95 .dtor = nvkm_vram_dtor,
96 .target = nvkm_vram_target,
97 .page = nvkm_vram_page,
98 .addr = nvkm_vram_addr,
99 .size = nvkm_vram_size,
100 .map = nvkm_vram_map,
101};
102
103int
104nvkm_ram_get(struct nvkm_device *device, u8 heap, u8 type, u8 rpage, u64 size,
105 bool contig, bool back, struct nvkm_memory **pmemory)
106{
107 struct nvkm_ram *ram;
108 struct nvkm_mm *mm;
109 struct nvkm_mm_node **node, *r;
110 struct nvkm_vram *vram;
111 u8 page = max(rpage, (u8)NVKM_RAM_MM_SHIFT);
112 u32 align = (1 << page) >> NVKM_RAM_MM_SHIFT;
113 u32 max = ALIGN(size, 1 << page) >> NVKM_RAM_MM_SHIFT;
114 u32 min = contig ? max : align;
115 int ret;
116
117 if (!device->fb || !(ram = device->fb->ram))
118 return -ENODEV;
119 ram = device->fb->ram;
120 mm = &ram->vram;
121
122 if (!(vram = kzalloc(sizeof(*vram), GFP_KERNEL)))
123 return -ENOMEM;
124 nvkm_memory_ctor(&nvkm_vram, &vram->memory);
125 vram->ram = ram;
126 vram->page = page;
127 *pmemory = &vram->memory;
128
129 mutex_lock(&ram->fb->subdev.mutex);
130 node = &vram->mn;
131 do {
132 if (back)
133 ret = nvkm_mm_tail(mm, heap, type, max, min, align, &r);
134 else
135 ret = nvkm_mm_head(mm, heap, type, max, min, align, &r);
136 if (ret) {
137 mutex_unlock(&ram->fb->subdev.mutex);
138 nvkm_memory_unref(pmemory);
139 return ret;
140 }
141
142 *node = r;
143 node = &r->next;
144 max -= r->length;
145 } while (max);
146 mutex_unlock(&ram->fb->subdev.mutex);
147 return 0;
148}
149
26int 150int
27nvkm_ram_init(struct nvkm_ram *ram) 151nvkm_ram_init(struct nvkm_ram *ram)
28{ 152{
@@ -38,7 +162,6 @@ nvkm_ram_del(struct nvkm_ram **pram)
38 if (ram && !WARN_ON(!ram->func)) { 162 if (ram && !WARN_ON(!ram->func)) {
39 if (ram->func->dtor) 163 if (ram->func->dtor)
40 *pram = ram->func->dtor(ram); 164 *pram = ram->func->dtor(ram);
41 nvkm_mm_fini(&ram->tags);
42 nvkm_mm_fini(&ram->vram); 165 nvkm_mm_fini(&ram->vram);
43 kfree(*pram); 166 kfree(*pram);
44 *pram = NULL; 167 *pram = NULL;
@@ -47,8 +170,7 @@ nvkm_ram_del(struct nvkm_ram **pram)
47 170
48int 171int
49nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, 172nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
50 enum nvkm_ram_type type, u64 size, u32 tags, 173 enum nvkm_ram_type type, u64 size, struct nvkm_ram *ram)
51 struct nvkm_ram *ram)
52{ 174{
53 static const char *name[] = { 175 static const char *name[] = {
54 [NVKM_RAM_TYPE_UNKNOWN] = "of unknown memory type", 176 [NVKM_RAM_TYPE_UNKNOWN] = "of unknown memory type",
@@ -73,28 +195,20 @@ nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
73 ram->size = size; 195 ram->size = size;
74 196
75 if (!nvkm_mm_initialised(&ram->vram)) { 197 if (!nvkm_mm_initialised(&ram->vram)) {
76 ret = nvkm_mm_init(&ram->vram, 0, size >> NVKM_RAM_MM_SHIFT, 1); 198 ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, 0,
199 size >> NVKM_RAM_MM_SHIFT, 1);
77 if (ret) 200 if (ret)
78 return ret; 201 return ret;
79 } 202 }
80 203
81 if (!nvkm_mm_initialised(&ram->tags)) {
82 ret = nvkm_mm_init(&ram->tags, 0, tags ? ++tags : 0, 1);
83 if (ret)
84 return ret;
85
86 nvkm_debug(subdev, "%d compression tags\n", tags);
87 }
88
89 return 0; 204 return 0;
90} 205}
91 206
92int 207int
93nvkm_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, 208nvkm_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
94 enum nvkm_ram_type type, u64 size, u32 tags, 209 enum nvkm_ram_type type, u64 size, struct nvkm_ram **pram)
95 struct nvkm_ram **pram)
96{ 210{
97 if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL))) 211 if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL)))
98 return -ENOMEM; 212 return -ENOMEM;
99 return nvkm_ram_ctor(func, fb, type, size, tags, *pram); 213 return nvkm_ram_ctor(func, fb, type, size, *pram);
100} 214}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
index fac7e73c3ddf..70fd59dcd06d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
@@ -3,11 +3,9 @@
3#include "priv.h" 3#include "priv.h"
4 4
5int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, 5int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
6 enum nvkm_ram_type, u64 size, u32 tags, 6 enum nvkm_ram_type, u64 size, struct nvkm_ram *);
7 struct nvkm_ram *);
8int nvkm_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, 7int nvkm_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *,
9 enum nvkm_ram_type, u64 size, u32 tags, 8 enum nvkm_ram_type, u64 size, struct nvkm_ram **);
10 struct nvkm_ram **);
11void nvkm_ram_del(struct nvkm_ram **); 9void nvkm_ram_del(struct nvkm_ram **);
12int nvkm_ram_init(struct nvkm_ram *); 10int nvkm_ram_init(struct nvkm_ram *);
13 11
@@ -15,9 +13,6 @@ extern const struct nvkm_ram_func nv04_ram_func;
15 13
16int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, 14int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
17 struct nvkm_ram *); 15 struct nvkm_ram *);
18int nv50_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
19void nv50_ram_put(struct nvkm_ram *, struct nvkm_mem **);
20void __nv50_ram_put(struct nvkm_ram *, struct nvkm_mem *);
21 16
22int gf100_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, 17int gf100_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *,
23 struct nvkm_ram **); 18 struct nvkm_ram **);
@@ -28,8 +23,6 @@ u32 gf100_ram_probe_fbp(const struct nvkm_ram_func *,
28u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, 23u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32,
29 struct nvkm_device *, int, int *); 24 struct nvkm_device *, int, int *);
30u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int); 25u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int);
31int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
32void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **);
33int gf100_ram_init(struct nvkm_ram *); 26int gf100_ram_init(struct nvkm_ram *);
34int gf100_ram_calc(struct nvkm_ram *, u32); 27int gf100_ram_calc(struct nvkm_ram *, u32);
35int gf100_ram_prog(struct nvkm_ram *); 28int gf100_ram_prog(struct nvkm_ram *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
index 4a9bd4f1cb93..ac87a3b6b7c9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
@@ -32,7 +32,6 @@
32#include <subdev/bios/timing.h> 32#include <subdev/bios/timing.h>
33#include <subdev/clk.h> 33#include <subdev/clk.h>
34#include <subdev/clk/pll.h> 34#include <subdev/clk/pll.h>
35#include <subdev/ltc.h>
36 35
37struct gf100_ramfuc { 36struct gf100_ramfuc {
38 struct ramfuc base; 37 struct ramfuc base;
@@ -420,86 +419,6 @@ gf100_ram_tidy(struct nvkm_ram *base)
420 ram_exec(&ram->fuc, false); 419 ram_exec(&ram->fuc, false);
421} 420}
422 421
423void
424gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem)
425{
426 struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc;
427 struct nvkm_mem *mem = *pmem;
428
429 *pmem = NULL;
430 if (unlikely(mem == NULL))
431 return;
432
433 mutex_lock(&ram->fb->subdev.mutex);
434 if (mem->tag)
435 nvkm_ltc_tags_free(ltc, &mem->tag);
436 __nv50_ram_put(ram, mem);
437 mutex_unlock(&ram->fb->subdev.mutex);
438
439 kfree(mem);
440}
441
442int
443gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin,
444 u32 memtype, struct nvkm_mem **pmem)
445{
446 struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc;
447 struct nvkm_mm *mm = &ram->vram;
448 struct nvkm_mm_node **node, *r;
449 struct nvkm_mem *mem;
450 int type = (memtype & 0x0ff);
451 int back = (memtype & 0x800);
452 const bool comp = gf100_pte_storage_type_map[type] != type;
453 int ret;
454
455 size >>= NVKM_RAM_MM_SHIFT;
456 align >>= NVKM_RAM_MM_SHIFT;
457 ncmin >>= NVKM_RAM_MM_SHIFT;
458 if (!ncmin)
459 ncmin = size;
460
461 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
462 if (!mem)
463 return -ENOMEM;
464
465 mem->size = size;
466
467 mutex_lock(&ram->fb->subdev.mutex);
468 if (comp) {
469 /* compression only works with lpages */
470 if (align == (1 << (17 - NVKM_RAM_MM_SHIFT))) {
471 int n = size >> 5;
472 nvkm_ltc_tags_alloc(ltc, n, &mem->tag);
473 }
474
475 if (unlikely(!mem->tag))
476 type = gf100_pte_storage_type_map[type];
477 }
478 mem->memtype = type;
479
480 node = &mem->mem;
481 do {
482 if (back)
483 ret = nvkm_mm_tail(mm, 0, 1, size, ncmin, align, &r);
484 else
485 ret = nvkm_mm_head(mm, 0, 1, size, ncmin, align, &r);
486 if (ret) {
487 mutex_unlock(&ram->fb->subdev.mutex);
488 ram->func->put(ram, &mem);
489 return ret;
490 }
491
492 *node = r;
493 node = &r->next;
494 size -= r->length;
495 } while (size);
496 mutex_unlock(&ram->fb->subdev.mutex);
497
498 mem->offset = (u64)mem->mem->offset << NVKM_RAM_MM_SHIFT;
499 *pmem = mem;
500 return 0;
501}
502
503int 422int
504gf100_ram_init(struct nvkm_ram *base) 423gf100_ram_init(struct nvkm_ram *base)
505{ 424{
@@ -604,7 +523,7 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
604 nvkm_debug(subdev, "Upper: %4lld MiB @ %010llx\n", usize >> 20, ubase); 523 nvkm_debug(subdev, "Upper: %4lld MiB @ %010llx\n", usize >> 20, ubase);
605 nvkm_debug(subdev, "Total: %4lld MiB\n", total >> 20); 524 nvkm_debug(subdev, "Total: %4lld MiB\n", total >> 20);
606 525
607 ret = nvkm_ram_ctor(func, fb, type, total, 0, ram); 526 ret = nvkm_ram_ctor(func, fb, type, total, ram);
608 if (ret) 527 if (ret)
609 return ret; 528 return ret;
610 529
@@ -617,7 +536,8 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
617 */ 536 */
618 if (lower != total) { 537 if (lower != total) {
619 /* The common memory amount is addressed normally. */ 538 /* The common memory amount is addressed normally. */
620 ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, 539 ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL,
540 rsvd_head >> NVKM_RAM_MM_SHIFT,
621 (lower - rsvd_head) >> NVKM_RAM_MM_SHIFT, 1); 541 (lower - rsvd_head) >> NVKM_RAM_MM_SHIFT, 1);
622 if (ret) 542 if (ret)
623 return ret; 543 return ret;
@@ -625,13 +545,15 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
625 /* And the rest is much higher in the physical address 545 /* And the rest is much higher in the physical address
626 * space, and may not be usable for certain operations. 546 * space, and may not be usable for certain operations.
627 */ 547 */
628 ret = nvkm_mm_init(&ram->vram, ubase >> NVKM_RAM_MM_SHIFT, 548 ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_MIXED,
549 ubase >> NVKM_RAM_MM_SHIFT,
629 (usize - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); 550 (usize - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1);
630 if (ret) 551 if (ret)
631 return ret; 552 return ret;
632 } else { 553 } else {
633 /* GPUs without mixed-memory are a lot nicer... */ 554 /* GPUs without mixed-memory are a lot nicer... */
634 ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, 555 ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL,
556 rsvd_head >> NVKM_RAM_MM_SHIFT,
635 (total - rsvd_head - rsvd_tail) >> 557 (total - rsvd_head - rsvd_tail) >>
636 NVKM_RAM_MM_SHIFT, 1); 558 NVKM_RAM_MM_SHIFT, 1);
637 if (ret) 559 if (ret)
@@ -738,8 +660,6 @@ gf100_ram = {
738 .probe_fbp_amount = gf100_ram_probe_fbp_amount, 660 .probe_fbp_amount = gf100_ram_probe_fbp_amount,
739 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, 661 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount,
740 .init = gf100_ram_init, 662 .init = gf100_ram_init,
741 .get = gf100_ram_get,
742 .put = gf100_ram_put,
743 .calc = gf100_ram_calc, 663 .calc = gf100_ram_calc,
744 .prog = gf100_ram_prog, 664 .prog = gf100_ram_prog,
745 .tidy = gf100_ram_tidy, 665 .tidy = gf100_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c
index 985ec64cf369..70a06e3cd55a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c
@@ -48,8 +48,6 @@ gf108_ram = {
48 .probe_fbp_amount = gf108_ram_probe_fbp_amount, 48 .probe_fbp_amount = gf108_ram_probe_fbp_amount,
49 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, 49 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount,
50 .init = gf100_ram_init, 50 .init = gf100_ram_init,
51 .get = gf100_ram_get,
52 .put = gf100_ram_put,
53 .calc = gf100_ram_calc, 51 .calc = gf100_ram_calc,
54 .prog = gf100_ram_prog, 52 .prog = gf100_ram_prog,
55 .tidy = gf100_ram_tidy, 53 .tidy = gf100_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
index 75814f15eb53..8bcb7e79a0cb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
@@ -1704,8 +1704,6 @@ gk104_ram = {
1704 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, 1704 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount,
1705 .dtor = gk104_ram_dtor, 1705 .dtor = gk104_ram_dtor,
1706 .init = gk104_ram_init, 1706 .init = gk104_ram_init,
1707 .get = gf100_ram_get,
1708 .put = gf100_ram_put,
1709 .calc = gk104_ram_calc, 1707 .calc = gk104_ram_calc,
1710 .prog = gk104_ram_prog, 1708 .prog = gk104_ram_prog,
1711 .tidy = gk104_ram_tidy, 1709 .tidy = gk104_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
index 3f0b56347291..27c68e3f9772 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
@@ -39,8 +39,6 @@ gm107_ram = {
39 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, 39 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount,
40 .dtor = gk104_ram_dtor, 40 .dtor = gk104_ram_dtor,
41 .init = gk104_ram_init, 41 .init = gk104_ram_init,
42 .get = gf100_ram_get,
43 .put = gf100_ram_put,
44 .calc = gk104_ram_calc, 42 .calc = gk104_ram_calc,
45 .prog = gk104_ram_prog, 43 .prog = gk104_ram_prog,
46 .tidy = gk104_ram_tidy, 44 .tidy = gk104_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c
index fd8facf90476..6b0cac1fe7b4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c
@@ -54,8 +54,6 @@ gm200_ram = {
54 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, 54 .probe_fbpa_amount = gf100_ram_probe_fbpa_amount,
55 .dtor = gk104_ram_dtor, 55 .dtor = gk104_ram_dtor,
56 .init = gk104_ram_init, 56 .init = gk104_ram_init,
57 .get = gf100_ram_get,
58 .put = gf100_ram_put,
59 .calc = gk104_ram_calc, 57 .calc = gk104_ram_calc,
60 .prog = gk104_ram_prog, 58 .prog = gk104_ram_prog,
61 .tidy = gk104_ram_tidy, 59 .tidy = gk104_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
index df8a87333b67..adb62a6beb63 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
@@ -84,8 +84,6 @@ gp100_ram = {
84 .probe_fbp_amount = gm200_ram_probe_fbp_amount, 84 .probe_fbp_amount = gm200_ram_probe_fbp_amount,
85 .probe_fbpa_amount = gp100_ram_probe_fbpa, 85 .probe_fbpa_amount = gp100_ram_probe_fbpa,
86 .init = gp100_ram_init, 86 .init = gp100_ram_init,
87 .get = gf100_ram_get,
88 .put = gf100_ram_put,
89}; 87};
90 88
91int 89int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index f10664372161..920b3d347803 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -26,6 +26,7 @@
26#include "ram.h" 26#include "ram.h"
27#include "ramfuc.h" 27#include "ramfuc.h"
28 28
29#include <core/memory.h>
29#include <core/option.h> 30#include <core/option.h>
30#include <subdev/bios.h> 31#include <subdev/bios.h>
31#include <subdev/bios/M0205.h> 32#include <subdev/bios/M0205.h>
@@ -86,7 +87,7 @@ struct gt215_ltrain {
86 u32 r_100720; 87 u32 r_100720;
87 u32 r_1111e0; 88 u32 r_1111e0;
88 u32 r_111400; 89 u32 r_111400;
89 struct nvkm_mem *mem; 90 struct nvkm_memory *memory;
90}; 91};
91 92
92struct gt215_ram { 93struct gt215_ram {
@@ -279,10 +280,10 @@ gt215_link_train_init(struct gt215_ram *ram)
279 struct gt215_ltrain *train = &ram->ltrain; 280 struct gt215_ltrain *train = &ram->ltrain;
280 struct nvkm_device *device = ram->base.fb->subdev.device; 281 struct nvkm_device *device = ram->base.fb->subdev.device;
281 struct nvkm_bios *bios = device->bios; 282 struct nvkm_bios *bios = device->bios;
282 struct nvkm_mem *mem;
283 struct nvbios_M0205E M0205E; 283 struct nvbios_M0205E M0205E;
284 u8 ver, hdr, cnt, len; 284 u8 ver, hdr, cnt, len;
285 u32 r001700; 285 u32 r001700;
286 u64 addr;
286 int ret, i = 0; 287 int ret, i = 0;
287 288
288 train->state = NVA3_TRAIN_UNSUPPORTED; 289 train->state = NVA3_TRAIN_UNSUPPORTED;
@@ -297,14 +298,14 @@ gt215_link_train_init(struct gt215_ram *ram)
297 298
298 train->state = NVA3_TRAIN_ONCE; 299 train->state = NVA3_TRAIN_ONCE;
299 300
300 ret = ram->base.func->get(&ram->base, 0x8000, 0x10000, 0, 0x800, 301 ret = nvkm_ram_get(device, NVKM_RAM_MM_NORMAL, 0x01, 16, 0x8000,
301 &ram->ltrain.mem); 302 true, true, &ram->ltrain.memory);
302 if (ret) 303 if (ret)
303 return ret; 304 return ret;
304 305
305 mem = ram->ltrain.mem; 306 addr = nvkm_memory_addr(ram->ltrain.memory);
306 307
307 nvkm_wr32(device, 0x100538, 0x10000000 | (mem->offset >> 16)); 308 nvkm_wr32(device, 0x100538, 0x10000000 | (addr >> 16));
308 nvkm_wr32(device, 0x1005a8, 0x0000ffff); 309 nvkm_wr32(device, 0x1005a8, 0x0000ffff);
309 nvkm_mask(device, 0x10f800, 0x00000001, 0x00000001); 310 nvkm_mask(device, 0x10f800, 0x00000001, 0x00000001);
310 311
@@ -320,7 +321,7 @@ gt215_link_train_init(struct gt215_ram *ram)
320 321
321 /* And upload the pattern */ 322 /* And upload the pattern */
322 r001700 = nvkm_rd32(device, 0x1700); 323 r001700 = nvkm_rd32(device, 0x1700);
323 nvkm_wr32(device, 0x1700, mem->offset >> 16); 324 nvkm_wr32(device, 0x1700, addr >> 16);
324 for (i = 0; i < 16; i++) 325 for (i = 0; i < 16; i++)
325 nvkm_wr32(device, 0x700000 + (i << 2), pattern[i]); 326 nvkm_wr32(device, 0x700000 + (i << 2), pattern[i]);
326 for (i = 0; i < 16; i++) 327 for (i = 0; i < 16; i++)
@@ -336,8 +337,7 @@ gt215_link_train_init(struct gt215_ram *ram)
336static void 337static void
337gt215_link_train_fini(struct gt215_ram *ram) 338gt215_link_train_fini(struct gt215_ram *ram)
338{ 339{
339 if (ram->ltrain.mem) 340 nvkm_memory_unref(&ram->ltrain.memory);
340 ram->base.func->put(&ram->base, &ram->ltrain.mem);
341} 341}
342 342
343/* 343/*
@@ -931,8 +931,6 @@ static const struct nvkm_ram_func
931gt215_ram_func = { 931gt215_ram_func = {
932 .dtor = gt215_ram_dtor, 932 .dtor = gt215_ram_dtor,
933 .init = gt215_ram_init, 933 .init = gt215_ram_init,
934 .get = nv50_ram_get,
935 .put = nv50_ram_put,
936 .calc = gt215_ram_calc, 934 .calc = gt215_ram_calc,
937 .prog = gt215_ram_prog, 935 .prog = gt215_ram_prog,
938 .tidy = gt215_ram_tidy, 936 .tidy = gt215_ram_tidy,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
index 017a91de74a0..7de18e53ef45 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c
@@ -53,8 +53,6 @@ mcp77_ram_init(struct nvkm_ram *base)
53static const struct nvkm_ram_func 53static const struct nvkm_ram_func
54mcp77_ram_func = { 54mcp77_ram_func = {
55 .init = mcp77_ram_init, 55 .init = mcp77_ram_init,
56 .get = nv50_ram_get,
57 .put = nv50_ram_put,
58}; 56};
59 57
60int 58int
@@ -73,7 +71,7 @@ mcp77_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
73 *pram = &ram->base; 71 *pram = &ram->base;
74 72
75 ret = nvkm_ram_ctor(&mcp77_ram_func, fb, NVKM_RAM_TYPE_STOLEN, 73 ret = nvkm_ram_ctor(&mcp77_ram_func, fb, NVKM_RAM_TYPE_STOLEN,
76 size, 0, &ram->base); 74 size, &ram->base);
77 if (ret) 75 if (ret)
78 return ret; 76 return ret;
79 77
@@ -81,7 +79,8 @@ mcp77_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
81 ram->base.stolen = base; 79 ram->base.stolen = base;
82 nvkm_mm_fini(&ram->base.vram); 80 nvkm_mm_fini(&ram->base.vram);
83 81
84 return nvkm_mm_init(&ram->base.vram, rsvd_head >> NVKM_RAM_MM_SHIFT, 82 return nvkm_mm_init(&ram->base.vram, NVKM_RAM_MM_NORMAL,
83 rsvd_head >> NVKM_RAM_MM_SHIFT,
85 (size - rsvd_head - rsvd_tail) >> 84 (size - rsvd_head - rsvd_tail) >>
86 NVKM_RAM_MM_SHIFT, 1); 85 NVKM_RAM_MM_SHIFT, 1);
87} 86}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c
index 6f053a03d61c..cc764a93f1a3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c
@@ -61,5 +61,5 @@ nv04_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
61 else 61 else
62 type = NVKM_RAM_TYPE_SDRAM; 62 type = NVKM_RAM_TYPE_SDRAM;
63 63
64 return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); 64 return nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram);
65} 65}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c
index dfd155c98dbb..afe54e323b18 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c
@@ -36,5 +36,5 @@ nv10_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
36 else 36 else
37 type = NVKM_RAM_TYPE_SDRAM; 37 type = NVKM_RAM_TYPE_SDRAM;
38 38
39 return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); 39 return nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram);
40} 40}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
index 3c6a8710e812..4c07d10bb976 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
@@ -44,5 +44,5 @@ nv1a_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
44 } 44 }
45 45
46 return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_STOLEN, 46 return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_STOLEN,
47 mib * 1024 * 1024, 0, pram); 47 mib * 1024 * 1024, pram);
48} 48}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c
index 747e47c10cc7..71d63d7daa75 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c
@@ -29,7 +29,6 @@ nv20_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
29 struct nvkm_device *device = fb->subdev.device; 29 struct nvkm_device *device = fb->subdev.device;
30 u32 pbus1218 = nvkm_rd32(device, 0x001218); 30 u32 pbus1218 = nvkm_rd32(device, 0x001218);
31 u32 size = (nvkm_rd32(device, 0x10020c) & 0xff000000); 31 u32 size = (nvkm_rd32(device, 0x10020c) & 0xff000000);
32 u32 tags = nvkm_rd32(device, 0x100320);
33 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; 32 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN;
34 int ret; 33 int ret;
35 34
@@ -40,7 +39,7 @@ nv20_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
40 case 0x00000300: type = NVKM_RAM_TYPE_GDDR2; break; 39 case 0x00000300: type = NVKM_RAM_TYPE_GDDR2; break;
41 } 40 }
42 41
43 ret = nvkm_ram_new_(&nv04_ram_func, fb, type, size, tags, pram); 42 ret = nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram);
44 if (ret) 43 if (ret)
45 return ret; 44 return ret;
46 45
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c
index 70c63535d56b..2b12e388f47a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c
@@ -187,13 +187,13 @@ nv40_ram_func = {
187 187
188int 188int
189nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type type, u64 size, 189nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type type, u64 size,
190 u32 tags, struct nvkm_ram **pram) 190 struct nvkm_ram **pram)
191{ 191{
192 struct nv40_ram *ram; 192 struct nv40_ram *ram;
193 if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) 193 if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL)))
194 return -ENOMEM; 194 return -ENOMEM;
195 *pram = &ram->base; 195 *pram = &ram->base;
196 return nvkm_ram_ctor(&nv40_ram_func, fb, type, size, tags, &ram->base); 196 return nvkm_ram_ctor(&nv40_ram_func, fb, type, size, &ram->base);
197} 197}
198 198
199int 199int
@@ -202,7 +202,6 @@ nv40_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
202 struct nvkm_device *device = fb->subdev.device; 202 struct nvkm_device *device = fb->subdev.device;
203 u32 pbus1218 = nvkm_rd32(device, 0x001218); 203 u32 pbus1218 = nvkm_rd32(device, 0x001218);
204 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; 204 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000;
205 u32 tags = nvkm_rd32(device, 0x100320);
206 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; 205 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN;
207 int ret; 206 int ret;
208 207
@@ -213,7 +212,7 @@ nv40_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
213 case 0x00000300: type = NVKM_RAM_TYPE_DDR2 ; break; 212 case 0x00000300: type = NVKM_RAM_TYPE_DDR2 ; break;
214 } 213 }
215 214
216 ret = nv40_ram_new_(fb, type, size, tags, pram); 215 ret = nv40_ram_new_(fb, type, size, pram);
217 if (ret) 216 if (ret)
218 return ret; 217 return ret;
219 218
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
index 8a0524566b48..ec5dcbfcaea8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h
@@ -9,6 +9,6 @@ struct nv40_ram {
9 u32 coef; 9 u32 coef;
10}; 10};
11 11
12int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64, u32, 12int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64,
13 struct nvkm_ram **); 13 struct nvkm_ram **);
14#endif 14#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c
index 114828be292e..d3fea3726461 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c
@@ -28,7 +28,6 @@ nv41_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
28{ 28{
29 struct nvkm_device *device = fb->subdev.device; 29 struct nvkm_device *device = fb->subdev.device;
30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; 30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000;
31 u32 tags = nvkm_rd32(device, 0x100320);
32 u32 fb474 = nvkm_rd32(device, 0x100474); 31 u32 fb474 = nvkm_rd32(device, 0x100474);
33 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; 32 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN;
34 int ret; 33 int ret;
@@ -40,7 +39,7 @@ nv41_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
40 if (fb474 & 0x00000001) 39 if (fb474 & 0x00000001)
41 type = NVKM_RAM_TYPE_DDR1; 40 type = NVKM_RAM_TYPE_DDR1;
42 41
43 ret = nv40_ram_new_(fb, type, size, tags, pram); 42 ret = nv40_ram_new_(fb, type, size, pram);
44 if (ret) 43 if (ret)
45 return ret; 44 return ret;
46 45
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c
index bc56fbf1c788..ab2630e5e6fb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c
@@ -38,5 +38,5 @@ nv44_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
38 if (fb474 & 0x00000001) 38 if (fb474 & 0x00000001)
39 type = NVKM_RAM_TYPE_DDR1; 39 type = NVKM_RAM_TYPE_DDR1;
40 40
41 return nv40_ram_new_(fb, type, size, 0, pram); 41 return nv40_ram_new_(fb, type, size, pram);
42} 42}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c
index c01f4b1022b8..946ca7c2e0b6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c
@@ -28,7 +28,6 @@ nv49_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
28{ 28{
29 struct nvkm_device *device = fb->subdev.device; 29 struct nvkm_device *device = fb->subdev.device;
30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; 30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000;
31 u32 tags = nvkm_rd32(device, 0x100320);
32 u32 fb914 = nvkm_rd32(device, 0x100914); 31 u32 fb914 = nvkm_rd32(device, 0x100914);
33 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; 32 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN;
34 int ret; 33 int ret;
@@ -40,7 +39,7 @@ nv49_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
40 case 0x00000003: break; 39 case 0x00000003: break;
41 } 40 }
42 41
43 ret = nv40_ram_new_(fb, type, size, tags, pram); 42 ret = nv40_ram_new_(fb, type, size, pram);
44 if (ret) 43 if (ret)
45 return ret; 44 return ret;
46 45
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c
index fa3c2e06203d..02b8bdbc819f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c
@@ -29,5 +29,5 @@ nv4e_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
29 struct nvkm_device *device = fb->subdev.device; 29 struct nvkm_device *device = fb->subdev.device;
30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; 30 u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000;
31 return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_UNKNOWN, 31 return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_UNKNOWN,
32 size, 0, pram); 32 size, pram);
33} 33}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index 6549b0588309..2ccb4b6be153 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -493,100 +493,8 @@ nv50_ram_tidy(struct nvkm_ram *base)
493 ram_exec(&ram->hwsq, false); 493 ram_exec(&ram->hwsq, false);
494} 494}
495 495
496void
497__nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem *mem)
498{
499 struct nvkm_mm_node *next = mem->mem;
500 struct nvkm_mm_node *node;
501 while ((node = next)) {
502 next = node->next;
503 nvkm_mm_free(&ram->vram, &node);
504 }
505 nvkm_mm_free(&ram->tags, &mem->tag);
506}
507
508void
509nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem)
510{
511 struct nvkm_mem *mem = *pmem;
512
513 *pmem = NULL;
514 if (unlikely(mem == NULL))
515 return;
516
517 mutex_lock(&ram->fb->subdev.mutex);
518 __nv50_ram_put(ram, mem);
519 mutex_unlock(&ram->fb->subdev.mutex);
520
521 kfree(mem);
522}
523
524int
525nv50_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin,
526 u32 memtype, struct nvkm_mem **pmem)
527{
528 struct nvkm_mm *heap = &ram->vram;
529 struct nvkm_mm *tags = &ram->tags;
530 struct nvkm_mm_node **node, *r;
531 struct nvkm_mem *mem;
532 int comp = (memtype & 0x300) >> 8;
533 int type = (memtype & 0x07f);
534 int back = (memtype & 0x800);
535 int min, max, ret;
536
537 max = (size >> NVKM_RAM_MM_SHIFT);
538 min = ncmin ? (ncmin >> NVKM_RAM_MM_SHIFT) : max;
539 align >>= NVKM_RAM_MM_SHIFT;
540
541 mem = kzalloc(sizeof(*mem), GFP_KERNEL);
542 if (!mem)
543 return -ENOMEM;
544
545 mutex_lock(&ram->fb->subdev.mutex);
546 if (comp) {
547 if (align == (1 << (16 - NVKM_RAM_MM_SHIFT))) {
548 int n = (max >> 4) * comp;
549
550 ret = nvkm_mm_head(tags, 0, 1, n, n, 1, &mem->tag);
551 if (ret)
552 mem->tag = NULL;
553 }
554
555 if (unlikely(!mem->tag))
556 comp = 0;
557 }
558
559 mem->memtype = (comp << 7) | type;
560 mem->size = max;
561
562 type = nv50_fb_memtype[type];
563 node = &mem->mem;
564 do {
565 if (back)
566 ret = nvkm_mm_tail(heap, 0, type, max, min, align, &r);
567 else
568 ret = nvkm_mm_head(heap, 0, type, max, min, align, &r);
569 if (ret) {
570 mutex_unlock(&ram->fb->subdev.mutex);
571 ram->func->put(ram, &mem);
572 return ret;
573 }
574
575 *node = r;
576 node = &r->next;
577 max -= r->length;
578 } while (max);
579 mutex_unlock(&ram->fb->subdev.mutex);
580
581 mem->offset = (u64)mem->mem->offset << NVKM_RAM_MM_SHIFT;
582 *pmem = mem;
583 return 0;
584}
585
586static const struct nvkm_ram_func 496static const struct nvkm_ram_func
587nv50_ram_func = { 497nv50_ram_func = {
588 .get = nv50_ram_get,
589 .put = nv50_ram_put,
590 .calc = nv50_ram_calc, 498 .calc = nv50_ram_calc,
591 .prog = nv50_ram_prog, 499 .prog = nv50_ram_prog,
592 .tidy = nv50_ram_tidy, 500 .tidy = nv50_ram_tidy,
@@ -639,7 +547,6 @@ nv50_ram_ctor(const struct nvkm_ram_func *func,
639 const u32 rsvd_head = ( 256 * 1024); /* vga memory */ 547 const u32 rsvd_head = ( 256 * 1024); /* vga memory */
640 const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ 548 const u32 rsvd_tail = (1024 * 1024); /* vbios etc */
641 u64 size = nvkm_rd32(device, 0x10020c); 549 u64 size = nvkm_rd32(device, 0x10020c);
642 u32 tags = nvkm_rd32(device, 0x100320);
643 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; 550 enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN;
644 int ret; 551 int ret;
645 552
@@ -660,7 +567,7 @@ nv50_ram_ctor(const struct nvkm_ram_func *func,
660 567
661 size = (size & 0x000000ff) << 32 | (size & 0xffffff00); 568 size = (size & 0x000000ff) << 32 | (size & 0xffffff00);
662 569
663 ret = nvkm_ram_ctor(func, fb, type, size, tags, ram); 570 ret = nvkm_ram_ctor(func, fb, type, size, ram);
664 if (ret) 571 if (ret)
665 return ret; 572 return ret;
666 573
@@ -669,7 +576,8 @@ nv50_ram_ctor(const struct nvkm_ram_func *func,
669 ram->ranks = (nvkm_rd32(device, 0x100200) & 0x4) ? 2 : 1; 576 ram->ranks = (nvkm_rd32(device, 0x100200) & 0x4) ? 2 : 1;
670 nvkm_mm_fini(&ram->vram); 577 nvkm_mm_fini(&ram->vram);
671 578
672 return nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, 579 return nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL,
580 rsvd_head >> NVKM_RAM_MM_SHIFT,
673 (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 581 (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT,
674 nv50_fb_vram_rblock(ram) >> NVKM_RAM_MM_SHIFT); 582 nv50_fb_vram_rblock(ram) >> NVKM_RAM_MM_SHIFT);
675} 583}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index 10c987a654ec..364ea4492acc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -23,181 +23,90 @@
23 */ 23 */
24#include "priv.h" 24#include "priv.h"
25 25
26#include <core/memory.h>
27#include <subdev/bar.h> 26#include <subdev/bar.h>
28 27
29/****************************************************************************** 28/******************************************************************************
30 * instmem object base implementation 29 * instmem object base implementation
31 *****************************************************************************/ 30 *****************************************************************************/
32#define nvkm_instobj(p) container_of((p), struct nvkm_instobj, memory)
33
34struct nvkm_instobj {
35 struct nvkm_memory memory;
36 struct nvkm_memory *parent;
37 struct nvkm_instmem *imem;
38 struct list_head head;
39 u32 *suspend;
40 void __iomem *map;
41};
42
43static enum nvkm_memory_target
44nvkm_instobj_target(struct nvkm_memory *memory)
45{
46 memory = nvkm_instobj(memory)->parent;
47 return nvkm_memory_target(memory);
48}
49
50static u64
51nvkm_instobj_addr(struct nvkm_memory *memory)
52{
53 memory = nvkm_instobj(memory)->parent;
54 return nvkm_memory_addr(memory);
55}
56
57static u64
58nvkm_instobj_size(struct nvkm_memory *memory)
59{
60 memory = nvkm_instobj(memory)->parent;
61 return nvkm_memory_size(memory);
62}
63
64static void 31static void
65nvkm_instobj_release(struct nvkm_memory *memory) 32nvkm_instobj_load(struct nvkm_instobj *iobj)
66{ 33{
67 struct nvkm_instobj *iobj = nvkm_instobj(memory); 34 struct nvkm_memory *memory = &iobj->memory;
68 nvkm_bar_flush(iobj->imem->subdev.device->bar); 35 const u64 size = nvkm_memory_size(memory);
69} 36 void __iomem *map;
70 37 int i;
71static void __iomem *
72nvkm_instobj_acquire(struct nvkm_memory *memory)
73{
74 return nvkm_instobj(memory)->map;
75}
76
77static u32
78nvkm_instobj_rd32(struct nvkm_memory *memory, u64 offset)
79{
80 return ioread32_native(nvkm_instobj(memory)->map + offset);
81}
82
83static void
84nvkm_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
85{
86 iowrite32_native(data, nvkm_instobj(memory)->map + offset);
87}
88 38
89static void 39 if (!(map = nvkm_kmap(memory))) {
90nvkm_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) 40 for (i = 0; i < size; i += 4)
91{ 41 nvkm_wo32(memory, i, iobj->suspend[i / 4]);
92 memory = nvkm_instobj(memory)->parent; 42 } else {
93 nvkm_memory_map(memory, vma, offset); 43 memcpy_toio(map, iobj->suspend, size);
94} 44 }
45 nvkm_done(memory);
95 46
96static void * 47 kvfree(iobj->suspend);
97nvkm_instobj_dtor(struct nvkm_memory *memory) 48 iobj->suspend = NULL;
98{
99 struct nvkm_instobj *iobj = nvkm_instobj(memory);
100 spin_lock(&iobj->imem->lock);
101 list_del(&iobj->head);
102 spin_unlock(&iobj->imem->lock);
103 nvkm_memory_del(&iobj->parent);
104 return iobj;
105} 49}
106 50
107static const struct nvkm_memory_func 51static int
108nvkm_instobj_func = { 52nvkm_instobj_save(struct nvkm_instobj *iobj)
109 .dtor = nvkm_instobj_dtor,
110 .target = nvkm_instobj_target,
111 .addr = nvkm_instobj_addr,
112 .size = nvkm_instobj_size,
113 .acquire = nvkm_instobj_acquire,
114 .release = nvkm_instobj_release,
115 .rd32 = nvkm_instobj_rd32,
116 .wr32 = nvkm_instobj_wr32,
117 .map = nvkm_instobj_map,
118};
119
120static void
121nvkm_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm)
122{ 53{
123 memory = nvkm_instobj(memory)->parent; 54 struct nvkm_memory *memory = &iobj->memory;
124 nvkm_memory_boot(memory, vm); 55 const u64 size = nvkm_memory_size(memory);
125} 56 void __iomem *map;
57 int i;
126 58
127static void 59 iobj->suspend = kvmalloc(size, GFP_KERNEL);
128nvkm_instobj_release_slow(struct nvkm_memory *memory) 60 if (!iobj->suspend)
129{ 61 return -ENOMEM;
130 struct nvkm_instobj *iobj = nvkm_instobj(memory);
131 nvkm_instobj_release(memory);
132 nvkm_done(iobj->parent);
133}
134 62
135static void __iomem * 63 if (!(map = nvkm_kmap(memory))) {
136nvkm_instobj_acquire_slow(struct nvkm_memory *memory) 64 for (i = 0; i < size; i += 4)
137{ 65 iobj->suspend[i / 4] = nvkm_ro32(memory, i);
138 struct nvkm_instobj *iobj = nvkm_instobj(memory); 66 } else {
139 iobj->map = nvkm_kmap(iobj->parent); 67 memcpy_fromio(iobj->suspend, map, size);
140 if (iobj->map) 68 }
141 memory->func = &nvkm_instobj_func; 69 nvkm_done(memory);
142 return iobj->map; 70 return 0;
143} 71}
144 72
145static u32 73void
146nvkm_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) 74nvkm_instobj_dtor(struct nvkm_instmem *imem, struct nvkm_instobj *iobj)
147{ 75{
148 struct nvkm_instobj *iobj = nvkm_instobj(memory); 76 spin_lock(&imem->lock);
149 return nvkm_ro32(iobj->parent, offset); 77 list_del(&iobj->head);
78 spin_unlock(&imem->lock);
150} 79}
151 80
152static void 81void
153nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) 82nvkm_instobj_ctor(const struct nvkm_memory_func *func,
83 struct nvkm_instmem *imem, struct nvkm_instobj *iobj)
154{ 84{
155 struct nvkm_instobj *iobj = nvkm_instobj(memory); 85 nvkm_memory_ctor(func, &iobj->memory);
156 return nvkm_wo32(iobj->parent, offset, data); 86 iobj->suspend = NULL;
87 spin_lock(&imem->lock);
88 list_add_tail(&iobj->head, &imem->list);
89 spin_unlock(&imem->lock);
157} 90}
158 91
159static const struct nvkm_memory_func
160nvkm_instobj_func_slow = {
161 .dtor = nvkm_instobj_dtor,
162 .target = nvkm_instobj_target,
163 .addr = nvkm_instobj_addr,
164 .size = nvkm_instobj_size,
165 .boot = nvkm_instobj_boot,
166 .acquire = nvkm_instobj_acquire_slow,
167 .release = nvkm_instobj_release_slow,
168 .rd32 = nvkm_instobj_rd32_slow,
169 .wr32 = nvkm_instobj_wr32_slow,
170 .map = nvkm_instobj_map,
171};
172
173int 92int
174nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, 93nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
175 struct nvkm_memory **pmemory) 94 struct nvkm_memory **pmemory)
176{ 95{
96 struct nvkm_subdev *subdev = &imem->subdev;
177 struct nvkm_memory *memory = NULL; 97 struct nvkm_memory *memory = NULL;
178 struct nvkm_instobj *iobj;
179 u32 offset; 98 u32 offset;
180 int ret; 99 int ret;
181 100
182 ret = imem->func->memory_new(imem, size, align, zero, &memory); 101 ret = imem->func->memory_new(imem, size, align, zero, &memory);
183 if (ret) 102 if (ret) {
103 nvkm_error(subdev, "OOM: %08x %08x %d\n", size, align, ret);
184 goto done; 104 goto done;
185
186 if (!imem->func->persistent) {
187 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) {
188 ret = -ENOMEM;
189 goto done;
190 }
191
192 nvkm_memory_ctor(&nvkm_instobj_func_slow, &iobj->memory);
193 iobj->parent = memory;
194 iobj->imem = imem;
195 spin_lock(&iobj->imem->lock);
196 list_add_tail(&iobj->head, &imem->list);
197 spin_unlock(&iobj->imem->lock);
198 memory = &iobj->memory;
199 } 105 }
200 106
107 nvkm_trace(subdev, "new %08x %08x %d: %010llx %010llx\n", size, align,
108 zero, nvkm_memory_addr(memory), nvkm_memory_size(memory));
109
201 if (!imem->func->zero && zero) { 110 if (!imem->func->zero && zero) {
202 void __iomem *map = nvkm_kmap(memory); 111 void __iomem *map = nvkm_kmap(memory);
203 if (unlikely(!map)) { 112 if (unlikely(!map)) {
@@ -211,7 +120,7 @@ nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
211 120
212done: 121done:
213 if (ret) 122 if (ret)
214 nvkm_memory_del(&memory); 123 nvkm_memory_unref(&memory);
215 *pmemory = memory; 124 *pmemory = memory;
216 return ret; 125 return ret;
217} 126}
@@ -232,39 +141,46 @@ nvkm_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 data)
232 return imem->func->wr32(imem, addr, data); 141 return imem->func->wr32(imem, addr, data);
233} 142}
234 143
144void
145nvkm_instmem_boot(struct nvkm_instmem *imem)
146{
147 /* Separate bootstrapped objects from normal list, as we need
148 * to make sure they're accessed with the slowpath on suspend
149 * and resume.
150 */
151 struct nvkm_instobj *iobj, *itmp;
152 spin_lock(&imem->lock);
153 list_for_each_entry_safe(iobj, itmp, &imem->list, head) {
154 list_move_tail(&iobj->head, &imem->boot);
155 }
156 spin_unlock(&imem->lock);
157}
158
235static int 159static int
236nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend) 160nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
237{ 161{
238 struct nvkm_instmem *imem = nvkm_instmem(subdev); 162 struct nvkm_instmem *imem = nvkm_instmem(subdev);
239 struct nvkm_instobj *iobj; 163 struct nvkm_instobj *iobj;
240 int i;
241
242 if (imem->func->fini)
243 imem->func->fini(imem);
244 164
245 if (suspend) { 165 if (suspend) {
246 list_for_each_entry(iobj, &imem->list, head) { 166 list_for_each_entry(iobj, &imem->list, head) {
247 struct nvkm_memory *memory = iobj->parent; 167 int ret = nvkm_instobj_save(iobj);
248 u64 size = nvkm_memory_size(memory); 168 if (ret)
169 return ret;
170 }
249 171
250 iobj->suspend = vmalloc(size); 172 nvkm_bar_bar2_fini(subdev->device);
251 if (!iobj->suspend)
252 return -ENOMEM;
253 173
254 for (i = 0; i < size; i += 4) 174 list_for_each_entry(iobj, &imem->boot, head) {
255 iobj->suspend[i / 4] = nvkm_ro32(memory, i); 175 int ret = nvkm_instobj_save(iobj);
176 if (ret)
177 return ret;
256 } 178 }
257 } 179 }
258 180
259 return 0; 181 if (imem->func->fini)
260} 182 imem->func->fini(imem);
261 183
262static int
263nvkm_instmem_oneinit(struct nvkm_subdev *subdev)
264{
265 struct nvkm_instmem *imem = nvkm_instmem(subdev);
266 if (imem->func->oneinit)
267 return imem->func->oneinit(imem);
268 return 0; 184 return 0;
269} 185}
270 186
@@ -273,22 +189,31 @@ nvkm_instmem_init(struct nvkm_subdev *subdev)
273{ 189{
274 struct nvkm_instmem *imem = nvkm_instmem(subdev); 190 struct nvkm_instmem *imem = nvkm_instmem(subdev);
275 struct nvkm_instobj *iobj; 191 struct nvkm_instobj *iobj;
276 int i; 192
193 list_for_each_entry(iobj, &imem->boot, head) {
194 if (iobj->suspend)
195 nvkm_instobj_load(iobj);
196 }
197
198 nvkm_bar_bar2_init(subdev->device);
277 199
278 list_for_each_entry(iobj, &imem->list, head) { 200 list_for_each_entry(iobj, &imem->list, head) {
279 if (iobj->suspend) { 201 if (iobj->suspend)
280 struct nvkm_memory *memory = iobj->parent; 202 nvkm_instobj_load(iobj);
281 u64 size = nvkm_memory_size(memory);
282 for (i = 0; i < size; i += 4)
283 nvkm_wo32(memory, i, iobj->suspend[i / 4]);
284 vfree(iobj->suspend);
285 iobj->suspend = NULL;
286 }
287 } 203 }
288 204
289 return 0; 205 return 0;
290} 206}
291 207
208static int
209nvkm_instmem_oneinit(struct nvkm_subdev *subdev)
210{
211 struct nvkm_instmem *imem = nvkm_instmem(subdev);
212 if (imem->func->oneinit)
213 return imem->func->oneinit(imem);
214 return 0;
215}
216
292static void * 217static void *
293nvkm_instmem_dtor(struct nvkm_subdev *subdev) 218nvkm_instmem_dtor(struct nvkm_subdev *subdev)
294{ 219{
@@ -315,4 +240,5 @@ nvkm_instmem_ctor(const struct nvkm_instmem_func *func,
315 imem->func = func; 240 imem->func = func;
316 spin_lock_init(&imem->lock); 241 spin_lock_init(&imem->lock);
317 INIT_LIST_HEAD(&imem->list); 242 INIT_LIST_HEAD(&imem->list);
243 INIT_LIST_HEAD(&imem->boot);
318} 244}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
index cd5adbec5e57..985f2990ab0d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
@@ -44,14 +44,13 @@
44#include "priv.h" 44#include "priv.h"
45 45
46#include <core/memory.h> 46#include <core/memory.h>
47#include <core/mm.h>
48#include <core/tegra.h> 47#include <core/tegra.h>
49#include <subdev/fb.h>
50#include <subdev/ltc.h> 48#include <subdev/ltc.h>
49#include <subdev/mmu.h>
51 50
52struct gk20a_instobj { 51struct gk20a_instobj {
53 struct nvkm_memory memory; 52 struct nvkm_memory memory;
54 struct nvkm_mem mem; 53 struct nvkm_mm_node *mn;
55 struct gk20a_instmem *imem; 54 struct gk20a_instmem *imem;
56 55
57 /* CPU mapping */ 56 /* CPU mapping */
@@ -119,16 +118,22 @@ gk20a_instobj_target(struct nvkm_memory *memory)
119 return NVKM_MEM_TARGET_NCOH; 118 return NVKM_MEM_TARGET_NCOH;
120} 119}
121 120
121static u8
122gk20a_instobj_page(struct nvkm_memory *memory)
123{
124 return 12;
125}
126
122static u64 127static u64
123gk20a_instobj_addr(struct nvkm_memory *memory) 128gk20a_instobj_addr(struct nvkm_memory *memory)
124{ 129{
125 return gk20a_instobj(memory)->mem.offset; 130 return (u64)gk20a_instobj(memory)->mn->offset << 12;
126} 131}
127 132
128static u64 133static u64
129gk20a_instobj_size(struct nvkm_memory *memory) 134gk20a_instobj_size(struct nvkm_memory *memory)
130{ 135{
131 return (u64)gk20a_instobj(memory)->mem.size << 12; 136 return (u64)gk20a_instobj(memory)->mn->length << 12;
132} 137}
133 138
134/* 139/*
@@ -272,12 +277,18 @@ gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
272 node->vaddr[offset / 4] = data; 277 node->vaddr[offset / 4] = data;
273} 278}
274 279
275static void 280static int
276gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) 281gk20a_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
282 struct nvkm_vma *vma, void *argv, u32 argc)
277{ 283{
278 struct gk20a_instobj *node = gk20a_instobj(memory); 284 struct gk20a_instobj *node = gk20a_instobj(memory);
285 struct nvkm_vmm_map map = {
286 .memory = &node->memory,
287 .offset = offset,
288 .mem = node->mn,
289 };
279 290
280 nvkm_vm_map_at(vma, offset, &node->mem); 291 return nvkm_vmm_map(vmm, vma, argv, argc, &map);
281} 292}
282 293
283static void * 294static void *
@@ -290,8 +301,8 @@ gk20a_instobj_dtor_dma(struct nvkm_memory *memory)
290 if (unlikely(!node->base.vaddr)) 301 if (unlikely(!node->base.vaddr))
291 goto out; 302 goto out;
292 303
293 dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->base.vaddr, 304 dma_free_attrs(dev, (u64)node->base.mn->length << PAGE_SHIFT,
294 node->handle, imem->attrs); 305 node->base.vaddr, node->handle, imem->attrs);
295 306
296out: 307out:
297 return node; 308 return node;
@@ -303,7 +314,7 @@ gk20a_instobj_dtor_iommu(struct nvkm_memory *memory)
303 struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); 314 struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory);
304 struct gk20a_instmem *imem = node->base.imem; 315 struct gk20a_instmem *imem = node->base.imem;
305 struct device *dev = imem->base.subdev.device->dev; 316 struct device *dev = imem->base.subdev.device->dev;
306 struct nvkm_mm_node *r = node->base.mem.mem; 317 struct nvkm_mm_node *r = node->base.mn;
307 int i; 318 int i;
308 319
309 if (unlikely(!r)) 320 if (unlikely(!r))
@@ -321,7 +332,7 @@ gk20a_instobj_dtor_iommu(struct nvkm_memory *memory)
321 r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift); 332 r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift);
322 333
323 /* Unmap pages from GPU address space and free them */ 334 /* Unmap pages from GPU address space and free them */
324 for (i = 0; i < node->base.mem.size; i++) { 335 for (i = 0; i < node->base.mn->length; i++) {
325 iommu_unmap(imem->domain, 336 iommu_unmap(imem->domain,
326 (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE); 337 (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE);
327 dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE, 338 dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE,
@@ -342,12 +353,11 @@ static const struct nvkm_memory_func
342gk20a_instobj_func_dma = { 353gk20a_instobj_func_dma = {
343 .dtor = gk20a_instobj_dtor_dma, 354 .dtor = gk20a_instobj_dtor_dma,
344 .target = gk20a_instobj_target, 355 .target = gk20a_instobj_target,
356 .page = gk20a_instobj_page,
345 .addr = gk20a_instobj_addr, 357 .addr = gk20a_instobj_addr,
346 .size = gk20a_instobj_size, 358 .size = gk20a_instobj_size,
347 .acquire = gk20a_instobj_acquire_dma, 359 .acquire = gk20a_instobj_acquire_dma,
348 .release = gk20a_instobj_release_dma, 360 .release = gk20a_instobj_release_dma,
349 .rd32 = gk20a_instobj_rd32,
350 .wr32 = gk20a_instobj_wr32,
351 .map = gk20a_instobj_map, 361 .map = gk20a_instobj_map,
352}; 362};
353 363
@@ -355,13 +365,18 @@ static const struct nvkm_memory_func
355gk20a_instobj_func_iommu = { 365gk20a_instobj_func_iommu = {
356 .dtor = gk20a_instobj_dtor_iommu, 366 .dtor = gk20a_instobj_dtor_iommu,
357 .target = gk20a_instobj_target, 367 .target = gk20a_instobj_target,
368 .page = gk20a_instobj_page,
358 .addr = gk20a_instobj_addr, 369 .addr = gk20a_instobj_addr,
359 .size = gk20a_instobj_size, 370 .size = gk20a_instobj_size,
360 .acquire = gk20a_instobj_acquire_iommu, 371 .acquire = gk20a_instobj_acquire_iommu,
361 .release = gk20a_instobj_release_iommu, 372 .release = gk20a_instobj_release_iommu,
373 .map = gk20a_instobj_map,
374};
375
376static const struct nvkm_memory_ptrs
377gk20a_instobj_ptrs = {
362 .rd32 = gk20a_instobj_rd32, 378 .rd32 = gk20a_instobj_rd32,
363 .wr32 = gk20a_instobj_wr32, 379 .wr32 = gk20a_instobj_wr32,
364 .map = gk20a_instobj_map,
365}; 380};
366 381
367static int 382static int
@@ -377,6 +392,7 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
377 *_node = &node->base; 392 *_node = &node->base;
378 393
379 nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory); 394 nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory);
395 node->base.memory.ptrs = &gk20a_instobj_ptrs;
380 396
381 node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, 397 node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
382 &node->handle, GFP_KERNEL, 398 &node->handle, GFP_KERNEL,
@@ -397,8 +413,7 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
397 node->r.offset = node->handle >> 12; 413 node->r.offset = node->handle >> 12;
398 node->r.length = (npages << PAGE_SHIFT) >> 12; 414 node->r.length = (npages << PAGE_SHIFT) >> 12;
399 415
400 node->base.mem.offset = node->handle; 416 node->base.mn = &node->r;
401 node->base.mem.mem = &node->r;
402 return 0; 417 return 0;
403} 418}
404 419
@@ -424,6 +439,7 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
424 node->dma_addrs = (void *)(node->pages + npages); 439 node->dma_addrs = (void *)(node->pages + npages);
425 440
426 nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory); 441 nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory);
442 node->base.memory.ptrs = &gk20a_instobj_ptrs;
427 443
428 /* Allocate backing memory */ 444 /* Allocate backing memory */
429 for (i = 0; i < npages; i++) { 445 for (i = 0; i < npages; i++) {
@@ -474,8 +490,7 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
474 /* IOMMU bit tells that an address is to be resolved through the IOMMU */ 490 /* IOMMU bit tells that an address is to be resolved through the IOMMU */
475 r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift); 491 r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift);
476 492
477 node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift; 493 node->base.mn = r;
478 node->base.mem.mem = r;
479 return 0; 494 return 0;
480 495
481release_area: 496release_area:
@@ -523,13 +538,8 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
523 538
524 node->imem = imem; 539 node->imem = imem;
525 540
526 /* present memory for being mapped using small pages */
527 node->mem.size = size >> 12;
528 node->mem.memtype = 0;
529 node->mem.page_shift = 12;
530
531 nvkm_debug(subdev, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n", 541 nvkm_debug(subdev, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n",
532 size, align, node->mem.offset); 542 size, align, (u64)node->mn->offset << 12);
533 543
534 return 0; 544 return 0;
535} 545}
@@ -554,7 +564,6 @@ static const struct nvkm_instmem_func
554gk20a_instmem = { 564gk20a_instmem = {
555 .dtor = gk20a_instmem_dtor, 565 .dtor = gk20a_instmem_dtor,
556 .memory_new = gk20a_instobj_new, 566 .memory_new = gk20a_instobj_new,
557 .persistent = true,
558 .zero = false, 567 .zero = false,
559}; 568};
560 569
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
index 6133c8bb2d42..6bf0dad46919 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
@@ -24,7 +24,6 @@
24#define nv04_instmem(p) container_of((p), struct nv04_instmem, base) 24#define nv04_instmem(p) container_of((p), struct nv04_instmem, base)
25#include "priv.h" 25#include "priv.h"
26 26
27#include <core/memory.h>
28#include <core/ramht.h> 27#include <core/ramht.h>
29 28
30struct nv04_instmem { 29struct nv04_instmem {
@@ -35,30 +34,39 @@ struct nv04_instmem {
35/****************************************************************************** 34/******************************************************************************
36 * instmem object implementation 35 * instmem object implementation
37 *****************************************************************************/ 36 *****************************************************************************/
38#define nv04_instobj(p) container_of((p), struct nv04_instobj, memory) 37#define nv04_instobj(p) container_of((p), struct nv04_instobj, base.memory)
39 38
40struct nv04_instobj { 39struct nv04_instobj {
41 struct nvkm_memory memory; 40 struct nvkm_instobj base;
42 struct nv04_instmem *imem; 41 struct nv04_instmem *imem;
43 struct nvkm_mm_node *node; 42 struct nvkm_mm_node *node;
44}; 43};
45 44
46static enum nvkm_memory_target 45static void
47nv04_instobj_target(struct nvkm_memory *memory) 46nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
48{ 47{
49 return NVKM_MEM_TARGET_INST; 48 struct nv04_instobj *iobj = nv04_instobj(memory);
49 struct nvkm_device *device = iobj->imem->base.subdev.device;
50 nvkm_wr32(device, 0x700000 + iobj->node->offset + offset, data);
50} 51}
51 52
52static u64 53static u32
53nv04_instobj_addr(struct nvkm_memory *memory) 54nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset)
54{ 55{
55 return nv04_instobj(memory)->node->offset; 56 struct nv04_instobj *iobj = nv04_instobj(memory);
57 struct nvkm_device *device = iobj->imem->base.subdev.device;
58 return nvkm_rd32(device, 0x700000 + iobj->node->offset + offset);
56} 59}
57 60
58static u64 61static const struct nvkm_memory_ptrs
59nv04_instobj_size(struct nvkm_memory *memory) 62nv04_instobj_ptrs = {
63 .rd32 = nv04_instobj_rd32,
64 .wr32 = nv04_instobj_wr32,
65};
66
67static void
68nv04_instobj_release(struct nvkm_memory *memory)
60{ 69{
61 return nv04_instobj(memory)->node->length;
62} 70}
63 71
64static void __iomem * 72static void __iomem *
@@ -69,25 +77,22 @@ nv04_instobj_acquire(struct nvkm_memory *memory)
69 return device->pri + 0x700000 + iobj->node->offset; 77 return device->pri + 0x700000 + iobj->node->offset;
70} 78}
71 79
72static void 80static u64
73nv04_instobj_release(struct nvkm_memory *memory) 81nv04_instobj_size(struct nvkm_memory *memory)
74{ 82{
83 return nv04_instobj(memory)->node->length;
75} 84}
76 85
77static u32 86static u64
78nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset) 87nv04_instobj_addr(struct nvkm_memory *memory)
79{ 88{
80 struct nv04_instobj *iobj = nv04_instobj(memory); 89 return nv04_instobj(memory)->node->offset;
81 struct nvkm_device *device = iobj->imem->base.subdev.device;
82 return nvkm_rd32(device, 0x700000 + iobj->node->offset + offset);
83} 90}
84 91
85static void 92static enum nvkm_memory_target
86nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) 93nv04_instobj_target(struct nvkm_memory *memory)
87{ 94{
88 struct nv04_instobj *iobj = nv04_instobj(memory); 95 return NVKM_MEM_TARGET_INST;
89 struct nvkm_device *device = iobj->imem->base.subdev.device;
90 nvkm_wr32(device, 0x700000 + iobj->node->offset + offset, data);
91} 96}
92 97
93static void * 98static void *
@@ -97,6 +102,7 @@ nv04_instobj_dtor(struct nvkm_memory *memory)
97 mutex_lock(&iobj->imem->base.subdev.mutex); 102 mutex_lock(&iobj->imem->base.subdev.mutex);
98 nvkm_mm_free(&iobj->imem->heap, &iobj->node); 103 nvkm_mm_free(&iobj->imem->heap, &iobj->node);
99 mutex_unlock(&iobj->imem->base.subdev.mutex); 104 mutex_unlock(&iobj->imem->base.subdev.mutex);
105 nvkm_instobj_dtor(&iobj->imem->base, &iobj->base);
100 return iobj; 106 return iobj;
101} 107}
102 108
@@ -108,8 +114,6 @@ nv04_instobj_func = {
108 .addr = nv04_instobj_addr, 114 .addr = nv04_instobj_addr,
109 .acquire = nv04_instobj_acquire, 115 .acquire = nv04_instobj_acquire,
110 .release = nv04_instobj_release, 116 .release = nv04_instobj_release,
111 .rd32 = nv04_instobj_rd32,
112 .wr32 = nv04_instobj_wr32,
113}; 117};
114 118
115static int 119static int
@@ -122,9 +126,10 @@ nv04_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
122 126
123 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) 127 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL)))
124 return -ENOMEM; 128 return -ENOMEM;
125 *pmemory = &iobj->memory; 129 *pmemory = &iobj->base.memory;
126 130
127 nvkm_memory_ctor(&nv04_instobj_func, &iobj->memory); 131 nvkm_instobj_ctor(&nv04_instobj_func, &imem->base, &iobj->base);
132 iobj->base.memory.ptrs = &nv04_instobj_ptrs;
128 iobj->imem = imem; 133 iobj->imem = imem;
129 134
130 mutex_lock(&imem->base.subdev.mutex); 135 mutex_lock(&imem->base.subdev.mutex);
@@ -160,7 +165,7 @@ nv04_instmem_oneinit(struct nvkm_instmem *base)
160 /* PRAMIN aperture maps over the end of VRAM, reserve it */ 165 /* PRAMIN aperture maps over the end of VRAM, reserve it */
161 imem->base.reserved = 512 * 1024; 166 imem->base.reserved = 512 * 1024;
162 167
163 ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); 168 ret = nvkm_mm_init(&imem->heap, 0, 0, imem->base.reserved, 1);
164 if (ret) 169 if (ret)
165 return ret; 170 return ret;
166 171
@@ -194,10 +199,10 @@ static void *
194nv04_instmem_dtor(struct nvkm_instmem *base) 199nv04_instmem_dtor(struct nvkm_instmem *base)
195{ 200{
196 struct nv04_instmem *imem = nv04_instmem(base); 201 struct nv04_instmem *imem = nv04_instmem(base);
197 nvkm_memory_del(&imem->base.ramfc); 202 nvkm_memory_unref(&imem->base.ramfc);
198 nvkm_memory_del(&imem->base.ramro); 203 nvkm_memory_unref(&imem->base.ramro);
199 nvkm_ramht_del(&imem->base.ramht); 204 nvkm_ramht_del(&imem->base.ramht);
200 nvkm_memory_del(&imem->base.vbios); 205 nvkm_memory_unref(&imem->base.vbios);
201 nvkm_mm_fini(&imem->heap); 206 nvkm_mm_fini(&imem->heap);
202 return imem; 207 return imem;
203} 208}
@@ -209,7 +214,6 @@ nv04_instmem = {
209 .rd32 = nv04_instmem_rd32, 214 .rd32 = nv04_instmem_rd32,
210 .wr32 = nv04_instmem_wr32, 215 .wr32 = nv04_instmem_wr32,
211 .memory_new = nv04_instobj_new, 216 .memory_new = nv04_instobj_new,
212 .persistent = false,
213 .zero = false, 217 .zero = false,
214}; 218};
215 219
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c
index c0543875e490..086c118488ef 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c
@@ -24,7 +24,6 @@
24#define nv40_instmem(p) container_of((p), struct nv40_instmem, base) 24#define nv40_instmem(p) container_of((p), struct nv40_instmem, base)
25#include "priv.h" 25#include "priv.h"
26 26
27#include <core/memory.h>
28#include <core/ramht.h> 27#include <core/ramht.h>
29#include <engine/gr/nv40.h> 28#include <engine/gr/nv40.h>
30 29
@@ -37,30 +36,38 @@ struct nv40_instmem {
37/****************************************************************************** 36/******************************************************************************
38 * instmem object implementation 37 * instmem object implementation
39 *****************************************************************************/ 38 *****************************************************************************/
40#define nv40_instobj(p) container_of((p), struct nv40_instobj, memory) 39#define nv40_instobj(p) container_of((p), struct nv40_instobj, base.memory)
41 40
42struct nv40_instobj { 41struct nv40_instobj {
43 struct nvkm_memory memory; 42 struct nvkm_instobj base;
44 struct nv40_instmem *imem; 43 struct nv40_instmem *imem;
45 struct nvkm_mm_node *node; 44 struct nvkm_mm_node *node;
46}; 45};
47 46
48static enum nvkm_memory_target 47static void
49nv40_instobj_target(struct nvkm_memory *memory) 48nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
50{ 49{
51 return NVKM_MEM_TARGET_INST; 50 struct nv40_instobj *iobj = nv40_instobj(memory);
51 iowrite32_native(data, iobj->imem->iomem + iobj->node->offset + offset);
52} 52}
53 53
54static u64 54static u32
55nv40_instobj_addr(struct nvkm_memory *memory) 55nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset)
56{ 56{
57 return nv40_instobj(memory)->node->offset; 57 struct nv40_instobj *iobj = nv40_instobj(memory);
58 return ioread32_native(iobj->imem->iomem + iobj->node->offset + offset);
58} 59}
59 60
60static u64 61static const struct nvkm_memory_ptrs
61nv40_instobj_size(struct nvkm_memory *memory) 62nv40_instobj_ptrs = {
63 .rd32 = nv40_instobj_rd32,
64 .wr32 = nv40_instobj_wr32,
65};
66
67static void
68nv40_instobj_release(struct nvkm_memory *memory)
62{ 69{
63 return nv40_instobj(memory)->node->length; 70 wmb();
64} 71}
65 72
66static void __iomem * 73static void __iomem *
@@ -70,23 +77,22 @@ nv40_instobj_acquire(struct nvkm_memory *memory)
70 return iobj->imem->iomem + iobj->node->offset; 77 return iobj->imem->iomem + iobj->node->offset;
71} 78}
72 79
73static void 80static u64
74nv40_instobj_release(struct nvkm_memory *memory) 81nv40_instobj_size(struct nvkm_memory *memory)
75{ 82{
83 return nv40_instobj(memory)->node->length;
76} 84}
77 85
78static u32 86static u64
79nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset) 87nv40_instobj_addr(struct nvkm_memory *memory)
80{ 88{
81 struct nv40_instobj *iobj = nv40_instobj(memory); 89 return nv40_instobj(memory)->node->offset;
82 return ioread32_native(iobj->imem->iomem + iobj->node->offset + offset);
83} 90}
84 91
85static void 92static enum nvkm_memory_target
86nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) 93nv40_instobj_target(struct nvkm_memory *memory)
87{ 94{
88 struct nv40_instobj *iobj = nv40_instobj(memory); 95 return NVKM_MEM_TARGET_INST;
89 iowrite32_native(data, iobj->imem->iomem + iobj->node->offset + offset);
90} 96}
91 97
92static void * 98static void *
@@ -96,6 +102,7 @@ nv40_instobj_dtor(struct nvkm_memory *memory)
96 mutex_lock(&iobj->imem->base.subdev.mutex); 102 mutex_lock(&iobj->imem->base.subdev.mutex);
97 nvkm_mm_free(&iobj->imem->heap, &iobj->node); 103 nvkm_mm_free(&iobj->imem->heap, &iobj->node);
98 mutex_unlock(&iobj->imem->base.subdev.mutex); 104 mutex_unlock(&iobj->imem->base.subdev.mutex);
105 nvkm_instobj_dtor(&iobj->imem->base, &iobj->base);
99 return iobj; 106 return iobj;
100} 107}
101 108
@@ -107,8 +114,6 @@ nv40_instobj_func = {
107 .addr = nv40_instobj_addr, 114 .addr = nv40_instobj_addr,
108 .acquire = nv40_instobj_acquire, 115 .acquire = nv40_instobj_acquire,
109 .release = nv40_instobj_release, 116 .release = nv40_instobj_release,
110 .rd32 = nv40_instobj_rd32,
111 .wr32 = nv40_instobj_wr32,
112}; 117};
113 118
114static int 119static int
@@ -121,9 +126,10 @@ nv40_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
121 126
122 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) 127 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL)))
123 return -ENOMEM; 128 return -ENOMEM;
124 *pmemory = &iobj->memory; 129 *pmemory = &iobj->base.memory;
125 130
126 nvkm_memory_ctor(&nv40_instobj_func, &iobj->memory); 131 nvkm_instobj_ctor(&nv40_instobj_func, &imem->base, &iobj->base);
132 iobj->base.memory.ptrs = &nv40_instobj_ptrs;
127 iobj->imem = imem; 133 iobj->imem = imem;
128 134
129 mutex_lock(&imem->base.subdev.mutex); 135 mutex_lock(&imem->base.subdev.mutex);
@@ -171,7 +177,7 @@ nv40_instmem_oneinit(struct nvkm_instmem *base)
171 imem->base.reserved += 512 * 1024; /* object storage */ 177 imem->base.reserved += 512 * 1024; /* object storage */
172 imem->base.reserved = round_up(imem->base.reserved, 4096); 178 imem->base.reserved = round_up(imem->base.reserved, 4096);
173 179
174 ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); 180 ret = nvkm_mm_init(&imem->heap, 0, 0, imem->base.reserved, 1);
175 if (ret) 181 if (ret)
176 return ret; 182 return ret;
177 183
@@ -209,10 +215,10 @@ static void *
209nv40_instmem_dtor(struct nvkm_instmem *base) 215nv40_instmem_dtor(struct nvkm_instmem *base)
210{ 216{
211 struct nv40_instmem *imem = nv40_instmem(base); 217 struct nv40_instmem *imem = nv40_instmem(base);
212 nvkm_memory_del(&imem->base.ramfc); 218 nvkm_memory_unref(&imem->base.ramfc);
213 nvkm_memory_del(&imem->base.ramro); 219 nvkm_memory_unref(&imem->base.ramro);
214 nvkm_ramht_del(&imem->base.ramht); 220 nvkm_ramht_del(&imem->base.ramht);
215 nvkm_memory_del(&imem->base.vbios); 221 nvkm_memory_unref(&imem->base.vbios);
216 nvkm_mm_fini(&imem->heap); 222 nvkm_mm_fini(&imem->heap);
217 if (imem->iomem) 223 if (imem->iomem)
218 iounmap(imem->iomem); 224 iounmap(imem->iomem);
@@ -226,7 +232,6 @@ nv40_instmem = {
226 .rd32 = nv40_instmem_rd32, 232 .rd32 = nv40_instmem_rd32,
227 .wr32 = nv40_instmem_wr32, 233 .wr32 = nv40_instmem_wr32,
228 .memory_new = nv40_instobj_new, 234 .memory_new = nv40_instobj_new,
229 .persistent = false,
230 .zero = false, 235 .zero = false,
231}; 236};
232 237
@@ -248,8 +253,8 @@ nv40_instmem_new(struct nvkm_device *device, int index,
248 else 253 else
249 bar = 3; 254 bar = 3;
250 255
251 imem->iomem = ioremap(device->func->resource_addr(device, bar), 256 imem->iomem = ioremap_wc(device->func->resource_addr(device, bar),
252 device->func->resource_size(device, bar)); 257 device->func->resource_size(device, bar));
253 if (!imem->iomem) { 258 if (!imem->iomem) {
254 nvkm_error(&imem->base.subdev, "unable to map PRAMIN BAR\n"); 259 nvkm_error(&imem->base.subdev, "unable to map PRAMIN BAR\n");
255 return -EFAULT; 260 return -EFAULT;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
index 6d512c062ae3..1ba7289684aa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -31,147 +31,293 @@
31 31
32struct nv50_instmem { 32struct nv50_instmem {
33 struct nvkm_instmem base; 33 struct nvkm_instmem base;
34 unsigned long lock_flags;
35 spinlock_t lock;
36 u64 addr; 34 u64 addr;
35
36 /* Mappings that can be evicted when BAR2 space has been exhausted. */
37 struct list_head lru;
37}; 38};
38 39
39/****************************************************************************** 40/******************************************************************************
40 * instmem object implementation 41 * instmem object implementation
41 *****************************************************************************/ 42 *****************************************************************************/
42#define nv50_instobj(p) container_of((p), struct nv50_instobj, memory) 43#define nv50_instobj(p) container_of((p), struct nv50_instobj, base.memory)
43 44
44struct nv50_instobj { 45struct nv50_instobj {
45 struct nvkm_memory memory; 46 struct nvkm_instobj base;
46 struct nv50_instmem *imem; 47 struct nv50_instmem *imem;
47 struct nvkm_mem *mem; 48 struct nvkm_memory *ram;
48 struct nvkm_vma bar; 49 struct nvkm_vma *bar;
50 refcount_t maps;
49 void *map; 51 void *map;
52 struct list_head lru;
50}; 53};
51 54
52static enum nvkm_memory_target 55static void
53nv50_instobj_target(struct nvkm_memory *memory) 56nv50_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data)
54{ 57{
55 return NVKM_MEM_TARGET_VRAM; 58 struct nv50_instobj *iobj = nv50_instobj(memory);
59 struct nv50_instmem *imem = iobj->imem;
60 struct nvkm_device *device = imem->base.subdev.device;
61 u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL;
62 u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL;
63 unsigned long flags;
64
65 spin_lock_irqsave(&imem->base.lock, flags);
66 if (unlikely(imem->addr != base)) {
67 nvkm_wr32(device, 0x001700, base >> 16);
68 imem->addr = base;
69 }
70 nvkm_wr32(device, 0x700000 + addr, data);
71 spin_unlock_irqrestore(&imem->base.lock, flags);
56} 72}
57 73
58static u64 74static u32
59nv50_instobj_addr(struct nvkm_memory *memory) 75nv50_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset)
60{ 76{
61 return nv50_instobj(memory)->mem->offset; 77 struct nv50_instobj *iobj = nv50_instobj(memory);
78 struct nv50_instmem *imem = iobj->imem;
79 struct nvkm_device *device = imem->base.subdev.device;
80 u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL;
81 u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL;
82 u32 data;
83 unsigned long flags;
84
85 spin_lock_irqsave(&imem->base.lock, flags);
86 if (unlikely(imem->addr != base)) {
87 nvkm_wr32(device, 0x001700, base >> 16);
88 imem->addr = base;
89 }
90 data = nvkm_rd32(device, 0x700000 + addr);
91 spin_unlock_irqrestore(&imem->base.lock, flags);
92 return data;
62} 93}
63 94
64static u64 95static const struct nvkm_memory_ptrs
65nv50_instobj_size(struct nvkm_memory *memory) 96nv50_instobj_slow = {
97 .rd32 = nv50_instobj_rd32_slow,
98 .wr32 = nv50_instobj_wr32_slow,
99};
100
101static void
102nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data)
66{ 103{
67 return (u64)nv50_instobj(memory)->mem->size << NVKM_RAM_MM_SHIFT; 104 iowrite32_native(data, nv50_instobj(memory)->map + offset);
68} 105}
69 106
107static u32
108nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset)
109{
110 return ioread32_native(nv50_instobj(memory)->map + offset);
111}
112
113static const struct nvkm_memory_ptrs
114nv50_instobj_fast = {
115 .rd32 = nv50_instobj_rd32,
116 .wr32 = nv50_instobj_wr32,
117};
118
70static void 119static void
71nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) 120nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
72{ 121{
73 struct nv50_instobj *iobj = nv50_instobj(memory); 122 struct nv50_instmem *imem = iobj->imem;
74 struct nvkm_subdev *subdev = &iobj->imem->base.subdev; 123 struct nv50_instobj *eobj;
124 struct nvkm_memory *memory = &iobj->base.memory;
125 struct nvkm_subdev *subdev = &imem->base.subdev;
75 struct nvkm_device *device = subdev->device; 126 struct nvkm_device *device = subdev->device;
127 struct nvkm_vma *bar = NULL, *ebar;
76 u64 size = nvkm_memory_size(memory); 128 u64 size = nvkm_memory_size(memory);
77 void __iomem *map; 129 void *emap;
78 int ret; 130 int ret;
79 131
80 iobj->map = ERR_PTR(-ENOMEM); 132 /* Attempt to allocate BAR2 address-space and map the object
81 133 * into it. The lock has to be dropped while doing this due
82 ret = nvkm_vm_get(vm, size, 12, NV_MEM_ACCESS_RW, &iobj->bar); 134 * to the possibility of recursion for page table allocation.
83 if (ret == 0) { 135 */
84 map = ioremap(device->func->resource_addr(device, 3) + 136 mutex_unlock(&subdev->mutex);
85 (u32)iobj->bar.offset, size); 137 while ((ret = nvkm_vmm_get(vmm, 12, size, &bar))) {
86 if (map) { 138 /* Evict unused mappings, and keep retrying until we either
87 nvkm_memory_map(memory, &iobj->bar, 0); 139 * succeed,or there's no more objects left on the LRU.
88 iobj->map = map; 140 */
89 } else { 141 mutex_lock(&subdev->mutex);
90 nvkm_warn(subdev, "PRAMIN ioremap failed\n"); 142 eobj = list_first_entry_or_null(&imem->lru, typeof(*eobj), lru);
91 nvkm_vm_put(&iobj->bar); 143 if (eobj) {
144 nvkm_debug(subdev, "evict %016llx %016llx @ %016llx\n",
145 nvkm_memory_addr(&eobj->base.memory),
146 nvkm_memory_size(&eobj->base.memory),
147 eobj->bar->addr);
148 list_del_init(&eobj->lru);
149 ebar = eobj->bar;
150 eobj->bar = NULL;
151 emap = eobj->map;
152 eobj->map = NULL;
92 } 153 }
93 } else { 154 mutex_unlock(&subdev->mutex);
94 nvkm_warn(subdev, "PRAMIN exhausted\n"); 155 if (!eobj)
156 break;
157 iounmap(emap);
158 nvkm_vmm_put(vmm, &ebar);
95 } 159 }
160
161 if (ret == 0)
162 ret = nvkm_memory_map(memory, 0, vmm, bar, NULL, 0);
163 mutex_lock(&subdev->mutex);
164 if (ret || iobj->bar) {
165 /* We either failed, or another thread beat us. */
166 mutex_unlock(&subdev->mutex);
167 nvkm_vmm_put(vmm, &bar);
168 mutex_lock(&subdev->mutex);
169 return;
170 }
171
172 /* Make the mapping visible to the host. */
173 iobj->bar = bar;
174 iobj->map = ioremap_wc(device->func->resource_addr(device, 3) +
175 (u32)iobj->bar->addr, size);
176 if (!iobj->map) {
177 nvkm_warn(subdev, "PRAMIN ioremap failed\n");
178 nvkm_vmm_put(vmm, &iobj->bar);
179 }
180}
181
182static int
183nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
184 struct nvkm_vma *vma, void *argv, u32 argc)
185{
186 memory = nv50_instobj(memory)->ram;
187 return nvkm_memory_map(memory, offset, vmm, vma, argv, argc);
96} 188}
97 189
98static void 190static void
99nv50_instobj_release(struct nvkm_memory *memory) 191nv50_instobj_release(struct nvkm_memory *memory)
100{ 192{
101 struct nv50_instmem *imem = nv50_instobj(memory)->imem; 193 struct nv50_instobj *iobj = nv50_instobj(memory);
102 spin_unlock_irqrestore(&imem->lock, imem->lock_flags); 194 struct nv50_instmem *imem = iobj->imem;
195 struct nvkm_subdev *subdev = &imem->base.subdev;
196
197 wmb();
198 nvkm_bar_flush(subdev->device->bar);
199
200 if (refcount_dec_and_mutex_lock(&iobj->maps, &subdev->mutex)) {
201 /* Add the now-unused mapping to the LRU instead of directly
202 * unmapping it here, in case we need to map it again later.
203 */
204 if (likely(iobj->lru.next) && iobj->map) {
205 BUG_ON(!list_empty(&iobj->lru));
206 list_add_tail(&iobj->lru, &imem->lru);
207 }
208
209 /* Switch back to NULL accessors when last map is gone. */
210 iobj->base.memory.ptrs = NULL;
211 mutex_unlock(&subdev->mutex);
212 }
103} 213}
104 214
105static void __iomem * 215static void __iomem *
106nv50_instobj_acquire(struct nvkm_memory *memory) 216nv50_instobj_acquire(struct nvkm_memory *memory)
107{ 217{
108 struct nv50_instobj *iobj = nv50_instobj(memory); 218 struct nv50_instobj *iobj = nv50_instobj(memory);
109 struct nv50_instmem *imem = iobj->imem; 219 struct nvkm_instmem *imem = &iobj->imem->base;
110 struct nvkm_bar *bar = imem->base.subdev.device->bar; 220 struct nvkm_vmm *vmm;
111 struct nvkm_vm *vm; 221 void __iomem *map = NULL;
112 unsigned long flags;
113 222
114 if (!iobj->map && (vm = nvkm_bar_kmap(bar))) 223 /* Already mapped? */
115 nvkm_memory_boot(memory, vm); 224 if (refcount_inc_not_zero(&iobj->maps))
116 if (!IS_ERR_OR_NULL(iobj->map))
117 return iobj->map; 225 return iobj->map;
118 226
119 spin_lock_irqsave(&imem->lock, flags); 227 /* Take the lock, and re-check that another thread hasn't
120 imem->lock_flags = flags; 228 * already mapped the object in the meantime.
121 return NULL; 229 */
122} 230 mutex_lock(&imem->subdev.mutex);
231 if (refcount_inc_not_zero(&iobj->maps)) {
232 mutex_unlock(&imem->subdev.mutex);
233 return iobj->map;
234 }
123 235
124static u32 236 /* Attempt to get a direct CPU mapping of the object. */
125nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) 237 if ((vmm = nvkm_bar_bar2_vmm(imem->subdev.device))) {
126{ 238 if (!iobj->map)
127 struct nv50_instobj *iobj = nv50_instobj(memory); 239 nv50_instobj_kmap(iobj, vmm);
128 struct nv50_instmem *imem = iobj->imem; 240 map = iobj->map;
129 struct nvkm_device *device = imem->base.subdev.device; 241 }
130 u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL;
131 u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL;
132 u32 data;
133 242
134 if (unlikely(imem->addr != base)) { 243 if (!refcount_inc_not_zero(&iobj->maps)) {
135 nvkm_wr32(device, 0x001700, base >> 16); 244 /* Exclude object from eviction while it's being accessed. */
136 imem->addr = base; 245 if (likely(iobj->lru.next))
246 list_del_init(&iobj->lru);
247
248 if (map)
249 iobj->base.memory.ptrs = &nv50_instobj_fast;
250 else
251 iobj->base.memory.ptrs = &nv50_instobj_slow;
252 refcount_inc(&iobj->maps);
137 } 253 }
138 data = nvkm_rd32(device, 0x700000 + addr); 254
139 return data; 255 mutex_unlock(&imem->subdev.mutex);
256 return map;
140} 257}
141 258
142static void 259static void
143nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) 260nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm)
144{ 261{
145 struct nv50_instobj *iobj = nv50_instobj(memory); 262 struct nv50_instobj *iobj = nv50_instobj(memory);
146 struct nv50_instmem *imem = iobj->imem; 263 struct nvkm_instmem *imem = &iobj->imem->base;
147 struct nvkm_device *device = imem->base.subdev.device; 264
148 u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL; 265 /* Exclude bootstrapped objects (ie. the page tables for the
149 u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL; 266 * instmem BAR itself) from eviction.
150 267 */
151 if (unlikely(imem->addr != base)) { 268 mutex_lock(&imem->subdev.mutex);
152 nvkm_wr32(device, 0x001700, base >> 16); 269 if (likely(iobj->lru.next)) {
153 imem->addr = base; 270 list_del_init(&iobj->lru);
271 iobj->lru.next = NULL;
154 } 272 }
155 nvkm_wr32(device, 0x700000 + addr, data); 273
274 nv50_instobj_kmap(iobj, vmm);
275 nvkm_instmem_boot(imem);
276 mutex_unlock(&imem->subdev.mutex);
156} 277}
157 278
158static void 279static u64
159nv50_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) 280nv50_instobj_size(struct nvkm_memory *memory)
160{ 281{
161 struct nv50_instobj *iobj = nv50_instobj(memory); 282 return nvkm_memory_size(nv50_instobj(memory)->ram);
162 nvkm_vm_map_at(vma, offset, iobj->mem); 283}
284
285static u64
286nv50_instobj_addr(struct nvkm_memory *memory)
287{
288 return nvkm_memory_addr(nv50_instobj(memory)->ram);
289}
290
291static enum nvkm_memory_target
292nv50_instobj_target(struct nvkm_memory *memory)
293{
294 return nvkm_memory_target(nv50_instobj(memory)->ram);
163} 295}
164 296
165static void * 297static void *
166nv50_instobj_dtor(struct nvkm_memory *memory) 298nv50_instobj_dtor(struct nvkm_memory *memory)
167{ 299{
168 struct nv50_instobj *iobj = nv50_instobj(memory); 300 struct nv50_instobj *iobj = nv50_instobj(memory);
169 struct nvkm_ram *ram = iobj->imem->base.subdev.device->fb->ram; 301 struct nvkm_instmem *imem = &iobj->imem->base;
170 if (!IS_ERR_OR_NULL(iobj->map)) { 302 struct nvkm_vma *bar;
171 nvkm_vm_put(&iobj->bar); 303 void *map = map;
172 iounmap(iobj->map); 304
305 mutex_lock(&imem->subdev.mutex);
306 if (likely(iobj->lru.next))
307 list_del(&iobj->lru);
308 map = iobj->map;
309 bar = iobj->bar;
310 mutex_unlock(&imem->subdev.mutex);
311
312 if (map) {
313 struct nvkm_vmm *vmm = nvkm_bar_bar2_vmm(imem->subdev.device);
314 iounmap(map);
315 if (likely(vmm)) /* Can be NULL during BAR destructor. */
316 nvkm_vmm_put(vmm, &bar);
173 } 317 }
174 ram->func->put(ram, &iobj->mem); 318
319 nvkm_memory_unref(&iobj->ram);
320 nvkm_instobj_dtor(imem, &iobj->base);
175 return iobj; 321 return iobj;
176} 322}
177 323
@@ -184,8 +330,6 @@ nv50_instobj_func = {
184 .boot = nv50_instobj_boot, 330 .boot = nv50_instobj_boot,
185 .acquire = nv50_instobj_acquire, 331 .acquire = nv50_instobj_acquire,
186 .release = nv50_instobj_release, 332 .release = nv50_instobj_release,
187 .rd32 = nv50_instobj_rd32,
188 .wr32 = nv50_instobj_wr32,
189 .map = nv50_instobj_map, 333 .map = nv50_instobj_map,
190}; 334};
191 335
@@ -195,25 +339,19 @@ nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
195{ 339{
196 struct nv50_instmem *imem = nv50_instmem(base); 340 struct nv50_instmem *imem = nv50_instmem(base);
197 struct nv50_instobj *iobj; 341 struct nv50_instobj *iobj;
198 struct nvkm_ram *ram = imem->base.subdev.device->fb->ram; 342 struct nvkm_device *device = imem->base.subdev.device;
199 int ret; 343 u8 page = max(order_base_2(align), 12);
200 344
201 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) 345 if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL)))
202 return -ENOMEM; 346 return -ENOMEM;
203 *pmemory = &iobj->memory; 347 *pmemory = &iobj->base.memory;
204 348
205 nvkm_memory_ctor(&nv50_instobj_func, &iobj->memory); 349 nvkm_instobj_ctor(&nv50_instobj_func, &imem->base, &iobj->base);
206 iobj->imem = imem; 350 iobj->imem = imem;
351 refcount_set(&iobj->maps, 0);
352 INIT_LIST_HEAD(&iobj->lru);
207 353
208 size = max((size + 4095) & ~4095, (u32)4096); 354 return nvkm_ram_get(device, 0, 1, page, size, true, true, &iobj->ram);
209 align = max((align + 4095) & ~4095, (u32)4096);
210
211 ret = ram->func->get(ram, size, align, 0, 0x800, &iobj->mem);
212 if (ret)
213 return ret;
214
215 iobj->mem->page_shift = 12;
216 return 0;
217} 355}
218 356
219/****************************************************************************** 357/******************************************************************************
@@ -230,7 +368,6 @@ static const struct nvkm_instmem_func
230nv50_instmem = { 368nv50_instmem = {
231 .fini = nv50_instmem_fini, 369 .fini = nv50_instmem_fini,
232 .memory_new = nv50_instobj_new, 370 .memory_new = nv50_instobj_new,
233 .persistent = false,
234 .zero = false, 371 .zero = false,
235}; 372};
236 373
@@ -243,7 +380,7 @@ nv50_instmem_new(struct nvkm_device *device, int index,
243 if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) 380 if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL)))
244 return -ENOMEM; 381 return -ENOMEM;
245 nvkm_instmem_ctor(&nv50_instmem, device, index, &imem->base); 382 nvkm_instmem_ctor(&nv50_instmem, device, index, &imem->base);
246 spin_lock_init(&imem->lock); 383 INIT_LIST_HEAD(&imem->lru);
247 *pimem = &imem->base; 384 *pimem = &imem->base;
248 return 0; 385 return 0;
249} 386}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
index ace4471864a3..44651ca42d52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -11,10 +11,22 @@ struct nvkm_instmem_func {
11 void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data); 11 void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data);
12 int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align, 12 int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align,
13 bool zero, struct nvkm_memory **); 13 bool zero, struct nvkm_memory **);
14 bool persistent;
15 bool zero; 14 bool zero;
16}; 15};
17 16
18void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *, 17void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
19 int index, struct nvkm_instmem *); 18 int index, struct nvkm_instmem *);
19void nvkm_instmem_boot(struct nvkm_instmem *);
20
21#include <core/memory.h>
22
23struct nvkm_instobj {
24 struct nvkm_memory memory;
25 struct list_head head;
26 u32 *suspend;
27};
28
29void nvkm_instobj_ctor(const struct nvkm_memory_func *func,
30 struct nvkm_instmem *, struct nvkm_instobj *);
31void nvkm_instobj_dtor(struct nvkm_instmem *, struct nvkm_instobj *);
20#endif 32#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
index 0c7ef250dcaf..1f185274d3e6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
@@ -23,26 +23,12 @@
23 */ 23 */
24#include "priv.h" 24#include "priv.h"
25 25
26#include <subdev/fb.h> 26#include <core/memory.h>
27
28int
29nvkm_ltc_tags_alloc(struct nvkm_ltc *ltc, u32 n, struct nvkm_mm_node **pnode)
30{
31 int ret = nvkm_mm_head(&ltc->tags, 0, 1, n, n, 1, pnode);
32 if (ret)
33 *pnode = NULL;
34 return ret;
35}
36
37void
38nvkm_ltc_tags_free(struct nvkm_ltc *ltc, struct nvkm_mm_node **pnode)
39{
40 nvkm_mm_free(&ltc->tags, pnode);
41}
42 27
43void 28void
44nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count) 29nvkm_ltc_tags_clear(struct nvkm_device *device, u32 first, u32 count)
45{ 30{
31 struct nvkm_ltc *ltc = device->ltc;
46 const u32 limit = first + count - 1; 32 const u32 limit = first + count - 1;
47 33
48 BUG_ON((first > limit) || (limit >= ltc->num_tags)); 34 BUG_ON((first > limit) || (limit >= ltc->num_tags));
@@ -116,10 +102,7 @@ static void *
116nvkm_ltc_dtor(struct nvkm_subdev *subdev) 102nvkm_ltc_dtor(struct nvkm_subdev *subdev)
117{ 103{
118 struct nvkm_ltc *ltc = nvkm_ltc(subdev); 104 struct nvkm_ltc *ltc = nvkm_ltc(subdev);
119 struct nvkm_ram *ram = ltc->subdev.device->fb->ram; 105 nvkm_memory_unref(&ltc->tag_ram);
120 nvkm_mm_fini(&ltc->tags);
121 if (ram)
122 nvkm_mm_free(&ram->vram, &ltc->tag_ram);
123 return ltc; 106 return ltc;
124} 107}
125 108
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
index 4a0fa0a9b802..a21ef45b8572 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
@@ -23,6 +23,7 @@
23 */ 23 */
24#include "priv.h" 24#include "priv.h"
25 25
26#include <core/memory.h>
26#include <subdev/fb.h> 27#include <subdev/fb.h>
27#include <subdev/timer.h> 28#include <subdev/timer.h>
28 29
@@ -152,7 +153,10 @@ gf100_ltc_flush(struct nvkm_ltc *ltc)
152int 153int
153gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) 154gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc)
154{ 155{
155 struct nvkm_ram *ram = ltc->subdev.device->fb->ram; 156 struct nvkm_device *device = ltc->subdev.device;
157 struct nvkm_fb *fb = device->fb;
158 struct nvkm_ram *ram = fb->ram;
159 u32 bits = (nvkm_rd32(device, 0x100c80) & 0x00001000) ? 16 : 17;
156 u32 tag_size, tag_margin, tag_align; 160 u32 tag_size, tag_margin, tag_align;
157 int ret; 161 int ret;
158 162
@@ -164,8 +168,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc)
164 168
165 /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ 169 /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
166 ltc->num_tags = (ram->size >> 17) / 4; 170 ltc->num_tags = (ram->size >> 17) / 4;
167 if (ltc->num_tags > (1 << 17)) 171 if (ltc->num_tags > (1 << bits))
168 ltc->num_tags = 1 << 17; /* we have 17 bits in PTE */ 172 ltc->num_tags = 1 << bits; /* we have 16/17 bits in PTE */
169 ltc->num_tags = (ltc->num_tags + 63) & ~63; /* round up to 64 */ 173 ltc->num_tags = (ltc->num_tags + 63) & ~63; /* round up to 64 */
170 174
171 tag_align = ltc->ltc_nr * 0x800; 175 tag_align = ltc->ltc_nr * 0x800;
@@ -181,14 +185,13 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc)
181 */ 185 */
182 tag_size = (ltc->num_tags / 64) * 0x6000 + tag_margin; 186 tag_size = (ltc->num_tags / 64) * 0x6000 + tag_margin;
183 tag_size += tag_align; 187 tag_size += tag_align;
184 tag_size = (tag_size + 0xfff) >> 12; /* round up */
185 188
186 ret = nvkm_mm_tail(&ram->vram, 1, 1, tag_size, tag_size, 1, 189 ret = nvkm_ram_get(device, NVKM_RAM_MM_NORMAL, 0x01, 12, tag_size,
187 &ltc->tag_ram); 190 true, true, &ltc->tag_ram);
188 if (ret) { 191 if (ret) {
189 ltc->num_tags = 0; 192 ltc->num_tags = 0;
190 } else { 193 } else {
191 u64 tag_base = ((u64)ltc->tag_ram->offset << 12) + tag_margin; 194 u64 tag_base = nvkm_memory_addr(ltc->tag_ram) + tag_margin;
192 195
193 tag_base += tag_align - 1; 196 tag_base += tag_align - 1;
194 do_div(tag_base, tag_align); 197 do_div(tag_base, tag_align);
@@ -197,7 +200,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc)
197 } 200 }
198 201
199mm_init: 202mm_init:
200 return nvkm_mm_init(&ltc->tags, 0, ltc->num_tags, 1); 203 nvkm_mm_fini(&fb->tags);
204 return nvkm_mm_init(&fb->tags, 0, 0, ltc->num_tags, 1);
201} 205}
202 206
203int 207int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
index 0bdfb2f40266..e34d42108019 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
@@ -45,7 +45,7 @@ gp100_ltc_oneinit(struct nvkm_ltc *ltc)
45 ltc->ltc_nr = nvkm_rd32(device, 0x12006c); 45 ltc->ltc_nr = nvkm_rd32(device, 0x12006c);
46 ltc->lts_nr = nvkm_rd32(device, 0x17e280) >> 28; 46 ltc->lts_nr = nvkm_rd32(device, 0x17e280) >> 28;
47 /*XXX: tagram allocation - TBD */ 47 /*XXX: tagram allocation - TBD */
48 return nvkm_mm_init(&ltc->tags, 0, 0, 1); 48 return 0;
49} 49}
50 50
51static void 51static void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
index 012c9db687b2..352a65f9371c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild
@@ -3,4 +3,33 @@ nvkm-y += nvkm/subdev/mmu/nv04.o
3nvkm-y += nvkm/subdev/mmu/nv41.o 3nvkm-y += nvkm/subdev/mmu/nv41.o
4nvkm-y += nvkm/subdev/mmu/nv44.o 4nvkm-y += nvkm/subdev/mmu/nv44.o
5nvkm-y += nvkm/subdev/mmu/nv50.o 5nvkm-y += nvkm/subdev/mmu/nv50.o
6nvkm-y += nvkm/subdev/mmu/g84.o
6nvkm-y += nvkm/subdev/mmu/gf100.o 7nvkm-y += nvkm/subdev/mmu/gf100.o
8nvkm-y += nvkm/subdev/mmu/gk104.o
9nvkm-y += nvkm/subdev/mmu/gk20a.o
10nvkm-y += nvkm/subdev/mmu/gm200.o
11nvkm-y += nvkm/subdev/mmu/gm20b.o
12nvkm-y += nvkm/subdev/mmu/gp100.o
13nvkm-y += nvkm/subdev/mmu/gp10b.o
14
15nvkm-y += nvkm/subdev/mmu/mem.o
16nvkm-y += nvkm/subdev/mmu/memnv04.o
17nvkm-y += nvkm/subdev/mmu/memnv50.o
18nvkm-y += nvkm/subdev/mmu/memgf100.o
19
20nvkm-y += nvkm/subdev/mmu/vmm.o
21nvkm-y += nvkm/subdev/mmu/vmmnv04.o
22nvkm-y += nvkm/subdev/mmu/vmmnv41.o
23nvkm-y += nvkm/subdev/mmu/vmmnv44.o
24nvkm-y += nvkm/subdev/mmu/vmmnv50.o
25nvkm-y += nvkm/subdev/mmu/vmmgf100.o
26nvkm-y += nvkm/subdev/mmu/vmmgk104.o
27nvkm-y += nvkm/subdev/mmu/vmmgk20a.o
28nvkm-y += nvkm/subdev/mmu/vmmgm200.o
29nvkm-y += nvkm/subdev/mmu/vmmgm20b.o
30nvkm-y += nvkm/subdev/mmu/vmmgp100.o
31nvkm-y += nvkm/subdev/mmu/vmmgp10b.o
32
33nvkm-y += nvkm/subdev/mmu/umem.o
34nvkm-y += nvkm/subdev/mmu/ummu.o
35nvkm-y += nvkm/subdev/mmu/uvmm.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
index 455da298227f..ee11ccaf0563 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -21,480 +21,367 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "priv.h" 24#include "ummu.h"
25#include "vmm.h"
25 26
26#include <core/gpuobj.h> 27#include <subdev/bar.h>
27#include <subdev/fb.h> 28#include <subdev/fb.h>
28 29
29void 30#include <nvif/if500d.h>
30nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) 31#include <nvif/if900d.h>
31{
32 struct nvkm_vm *vm = vma->vm;
33 struct nvkm_mmu *mmu = vm->mmu;
34 struct nvkm_mm_node *r = node->mem;
35 int big = vma->node->type != mmu->func->spg_shift;
36 u32 offset = vma->node->offset + (delta >> 12);
37 u32 bits = vma->node->type - 12;
38 u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
39 u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
40 u32 max = 1 << (mmu->func->pgt_bits - bits);
41 u32 end, len;
42
43 delta = 0;
44 while (r) {
45 u64 phys = (u64)r->offset << 12;
46 u32 num = r->length >> bits;
47
48 while (num) {
49 struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
50
51 end = (pte + num);
52 if (unlikely(end >= max))
53 end = max;
54 len = end - pte;
55
56 mmu->func->map(vma, pgt, node, pte, len, phys, delta);
57
58 num -= len;
59 pte += len;
60 if (unlikely(end >= max)) {
61 phys += len << (bits + 12);
62 pde++;
63 pte = 0;
64 }
65
66 delta += (u64)len << vma->node->type;
67 }
68 r = r->next;
69 };
70
71 mmu->func->flush(vm);
72}
73 32
74static void 33struct nvkm_mmu_ptp {
75nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, 34 struct nvkm_mmu_pt *pt;
76 struct nvkm_mem *mem) 35 struct list_head head;
77{ 36 u8 shift;
78 struct nvkm_vm *vm = vma->vm; 37 u16 mask;
79 struct nvkm_mmu *mmu = vm->mmu; 38 u16 free;
80 int big = vma->node->type != mmu->func->spg_shift; 39};
81 u32 offset = vma->node->offset + (delta >> 12);
82 u32 bits = vma->node->type - 12;
83 u32 num = length >> vma->node->type;
84 u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
85 u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
86 u32 max = 1 << (mmu->func->pgt_bits - bits);
87 unsigned m, sglen;
88 u32 end, len;
89 int i;
90 struct scatterlist *sg;
91
92 for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) {
93 struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
94 sglen = sg_dma_len(sg) >> PAGE_SHIFT;
95
96 end = pte + sglen;
97 if (unlikely(end >= max))
98 end = max;
99 len = end - pte;
100
101 for (m = 0; m < len; m++) {
102 dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
103
104 mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr);
105 num--;
106 pte++;
107
108 if (num == 0)
109 goto finish;
110 }
111 if (unlikely(end >= max)) {
112 pde++;
113 pte = 0;
114 }
115 if (m < sglen) {
116 for (; m < sglen; m++) {
117 dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
118
119 mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr);
120 num--;
121 pte++;
122 if (num == 0)
123 goto finish;
124 }
125 }
126
127 }
128finish:
129 mmu->func->flush(vm);
130}
131 40
132static void 41static void
133nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length, 42nvkm_mmu_ptp_put(struct nvkm_mmu *mmu, bool force, struct nvkm_mmu_pt *pt)
134 struct nvkm_mem *mem)
135{ 43{
136 struct nvkm_vm *vm = vma->vm; 44 const int slot = pt->base >> pt->ptp->shift;
137 struct nvkm_mmu *mmu = vm->mmu; 45 struct nvkm_mmu_ptp *ptp = pt->ptp;
138 dma_addr_t *list = mem->pages; 46
139 int big = vma->node->type != mmu->func->spg_shift; 47 /* If there were no free slots in the parent allocation before,
140 u32 offset = vma->node->offset + (delta >> 12); 48 * there will be now, so return PTP to the cache.
141 u32 bits = vma->node->type - 12; 49 */
142 u32 num = length >> vma->node->type; 50 if (!ptp->free)
143 u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; 51 list_add(&ptp->head, &mmu->ptp.list);
144 u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; 52 ptp->free |= BIT(slot);
145 u32 max = 1 << (mmu->func->pgt_bits - bits); 53
146 u32 end, len; 54 /* If there's no more sub-allocations, destroy PTP. */
147 55 if (ptp->free == ptp->mask) {
148 while (num) { 56 nvkm_mmu_ptc_put(mmu, force, &ptp->pt);
149 struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; 57 list_del(&ptp->head);
150 58 kfree(ptp);
151 end = (pte + num);
152 if (unlikely(end >= max))
153 end = max;
154 len = end - pte;
155
156 mmu->func->map_sg(vma, pgt, mem, pte, len, list);
157
158 num -= len;
159 pte += len;
160 list += len;
161 if (unlikely(end >= max)) {
162 pde++;
163 pte = 0;
164 }
165 } 59 }
166 60
167 mmu->func->flush(vm); 61 kfree(pt);
168} 62}
169 63
170void 64struct nvkm_mmu_pt *
171nvkm_vm_map(struct nvkm_vma *vma, struct nvkm_mem *node) 65nvkm_mmu_ptp_get(struct nvkm_mmu *mmu, u32 size, bool zero)
172{ 66{
173 if (node->sg) 67 struct nvkm_mmu_pt *pt;
174 nvkm_vm_map_sg_table(vma, 0, node->size << 12, node); 68 struct nvkm_mmu_ptp *ptp;
175 else 69 int slot;
176 if (node->pages) 70
177 nvkm_vm_map_sg(vma, 0, node->size << 12, node); 71 if (!(pt = kzalloc(sizeof(*pt), GFP_KERNEL)))
178 else 72 return NULL;
179 nvkm_vm_map_at(vma, 0, node); 73
180} 74 ptp = list_first_entry_or_null(&mmu->ptp.list, typeof(*ptp), head);
75 if (!ptp) {
76 /* Need to allocate a new parent to sub-allocate from. */
77 if (!(ptp = kmalloc(sizeof(*ptp), GFP_KERNEL))) {
78 kfree(pt);
79 return NULL;
80 }
181 81
182void 82 ptp->pt = nvkm_mmu_ptc_get(mmu, 0x1000, 0x1000, false);
183nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length) 83 if (!ptp->pt) {
184{ 84 kfree(ptp);
185 struct nvkm_vm *vm = vma->vm; 85 kfree(pt);
186 struct nvkm_mmu *mmu = vm->mmu; 86 return NULL;
187 int big = vma->node->type != mmu->func->spg_shift;
188 u32 offset = vma->node->offset + (delta >> 12);
189 u32 bits = vma->node->type - 12;
190 u32 num = length >> vma->node->type;
191 u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde;
192 u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits;
193 u32 max = 1 << (mmu->func->pgt_bits - bits);
194 u32 end, len;
195
196 while (num) {
197 struct nvkm_memory *pgt = vm->pgt[pde].mem[big];
198
199 end = (pte + num);
200 if (unlikely(end >= max))
201 end = max;
202 len = end - pte;
203
204 mmu->func->unmap(vma, pgt, pte, len);
205
206 num -= len;
207 pte += len;
208 if (unlikely(end >= max)) {
209 pde++;
210 pte = 0;
211 } 87 }
212 }
213 88
214 mmu->func->flush(vm); 89 ptp->shift = order_base_2(size);
90 slot = nvkm_memory_size(ptp->pt->memory) >> ptp->shift;
91 ptp->mask = (1 << slot) - 1;
92 ptp->free = ptp->mask;
93 list_add(&ptp->head, &mmu->ptp.list);
94 }
95 pt->ptp = ptp;
96 pt->sub = true;
97
98 /* Sub-allocate from parent object, removing PTP from cache
99 * if there's no more free slots left.
100 */
101 slot = __ffs(ptp->free);
102 ptp->free &= ~BIT(slot);
103 if (!ptp->free)
104 list_del(&ptp->head);
105
106 pt->memory = pt->ptp->pt->memory;
107 pt->base = slot << ptp->shift;
108 pt->addr = pt->ptp->pt->addr + pt->base;
109 return pt;
215} 110}
216 111
217void 112struct nvkm_mmu_ptc {
218nvkm_vm_unmap(struct nvkm_vma *vma) 113 struct list_head head;
219{ 114 struct list_head item;
220 nvkm_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); 115 u32 size;
221} 116 u32 refs;
117};
222 118
223static void 119static inline struct nvkm_mmu_ptc *
224nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) 120nvkm_mmu_ptc_find(struct nvkm_mmu *mmu, u32 size)
225{ 121{
226 struct nvkm_mmu *mmu = vm->mmu; 122 struct nvkm_mmu_ptc *ptc;
227 struct nvkm_vm_pgd *vpgd;
228 struct nvkm_vm_pgt *vpgt;
229 struct nvkm_memory *pgt;
230 u32 pde;
231
232 for (pde = fpde; pde <= lpde; pde++) {
233 vpgt = &vm->pgt[pde - vm->fpde];
234 if (--vpgt->refcount[big])
235 continue;
236
237 pgt = vpgt->mem[big];
238 vpgt->mem[big] = NULL;
239
240 list_for_each_entry(vpgd, &vm->pgd_list, head) {
241 mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
242 }
243 123
244 mmu->func->flush(vm); 124 list_for_each_entry(ptc, &mmu->ptc.list, head) {
125 if (ptc->size == size)
126 return ptc;
127 }
245 128
246 nvkm_memory_del(&pgt); 129 ptc = kmalloc(sizeof(*ptc), GFP_KERNEL);
130 if (ptc) {
131 INIT_LIST_HEAD(&ptc->item);
132 ptc->size = size;
133 ptc->refs = 0;
134 list_add(&ptc->head, &mmu->ptc.list);
247 } 135 }
136
137 return ptc;
248} 138}
249 139
250static int 140void
251nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type) 141nvkm_mmu_ptc_put(struct nvkm_mmu *mmu, bool force, struct nvkm_mmu_pt **ppt)
252{ 142{
253 struct nvkm_mmu *mmu = vm->mmu; 143 struct nvkm_mmu_pt *pt = *ppt;
254 struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; 144 if (pt) {
255 struct nvkm_vm_pgd *vpgd; 145 /* Handle sub-allocated page tables. */
256 int big = (type != mmu->func->spg_shift); 146 if (pt->sub) {
257 u32 pgt_size; 147 mutex_lock(&mmu->ptp.mutex);
258 int ret; 148 nvkm_mmu_ptp_put(mmu, force, pt);
259 149 mutex_unlock(&mmu->ptp.mutex);
260 pgt_size = (1 << (mmu->func->pgt_bits + 12)) >> type; 150 return;
261 pgt_size *= 8; 151 }
262
263 ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST,
264 pgt_size, 0x1000, true, &vpgt->mem[big]);
265 if (unlikely(ret))
266 return ret;
267 152
268 list_for_each_entry(vpgd, &vm->pgd_list, head) { 153 /* Either cache or free the object. */
269 mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); 154 mutex_lock(&mmu->ptc.mutex);
155 if (pt->ptc->refs < 8 /* Heuristic. */ && !force) {
156 list_add_tail(&pt->head, &pt->ptc->item);
157 pt->ptc->refs++;
158 } else {
159 nvkm_memory_unref(&pt->memory);
160 kfree(pt);
161 }
162 mutex_unlock(&mmu->ptc.mutex);
270 } 163 }
271
272 vpgt->refcount[big]++;
273 return 0;
274} 164}
275 165
276int 166struct nvkm_mmu_pt *
277nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, 167nvkm_mmu_ptc_get(struct nvkm_mmu *mmu, u32 size, u32 align, bool zero)
278 struct nvkm_vma *vma)
279{ 168{
280 struct nvkm_mmu *mmu = vm->mmu; 169 struct nvkm_mmu_ptc *ptc;
281 u32 align = (1 << page_shift) >> 12; 170 struct nvkm_mmu_pt *pt;
282 u32 msize = size >> 12;
283 u32 fpde, lpde, pde;
284 int ret; 171 int ret;
285 172
286 mutex_lock(&vm->mutex); 173 /* Sub-allocated page table (ie. GP100 LPT). */
287 ret = nvkm_mm_head(&vm->mm, 0, page_shift, msize, msize, align, 174 if (align < 0x1000) {
288 &vma->node); 175 mutex_lock(&mmu->ptp.mutex);
289 if (unlikely(ret != 0)) { 176 pt = nvkm_mmu_ptp_get(mmu, align, zero);
290 mutex_unlock(&vm->mutex); 177 mutex_unlock(&mmu->ptp.mutex);
291 return ret; 178 return pt;
292 } 179 }
293 180
294 fpde = (vma->node->offset >> mmu->func->pgt_bits); 181 /* Lookup cache for this page table size. */
295 lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits; 182 mutex_lock(&mmu->ptc.mutex);
183 ptc = nvkm_mmu_ptc_find(mmu, size);
184 if (!ptc) {
185 mutex_unlock(&mmu->ptc.mutex);
186 return NULL;
187 }
296 188
297 for (pde = fpde; pde <= lpde; pde++) { 189 /* If there's a free PT in the cache, reuse it. */
298 struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; 190 pt = list_first_entry_or_null(&ptc->item, typeof(*pt), head);
299 int big = (vma->node->type != mmu->func->spg_shift); 191 if (pt) {
192 if (zero)
193 nvkm_fo64(pt->memory, 0, 0, size >> 3);
194 list_del(&pt->head);
195 ptc->refs--;
196 mutex_unlock(&mmu->ptc.mutex);
197 return pt;
198 }
199 mutex_unlock(&mmu->ptc.mutex);
300 200
301 if (likely(vpgt->refcount[big])) { 201 /* No such luck, we need to allocate. */
302 vpgt->refcount[big]++; 202 if (!(pt = kmalloc(sizeof(*pt), GFP_KERNEL)))
303 continue; 203 return NULL;
304 } 204 pt->ptc = ptc;
205 pt->sub = false;
305 206
306 ret = nvkm_vm_map_pgt(vm, pde, vma->node->type); 207 ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST,
307 if (ret) { 208 size, align, zero, &pt->memory);
308 if (pde != fpde) 209 if (ret) {
309 nvkm_vm_unmap_pgt(vm, big, fpde, pde - 1); 210 kfree(pt);
310 nvkm_mm_free(&vm->mm, &vma->node); 211 return NULL;
311 mutex_unlock(&vm->mutex);
312 return ret;
313 }
314 } 212 }
315 mutex_unlock(&vm->mutex);
316 213
317 vma->vm = NULL; 214 pt->base = 0;
318 nvkm_vm_ref(vm, &vma->vm, NULL); 215 pt->addr = nvkm_memory_addr(pt->memory);
319 vma->offset = (u64)vma->node->offset << 12; 216 return pt;
320 vma->access = access;
321 return 0;
322} 217}
323 218
324void 219void
325nvkm_vm_put(struct nvkm_vma *vma) 220nvkm_mmu_ptc_dump(struct nvkm_mmu *mmu)
326{
327 struct nvkm_mmu *mmu;
328 struct nvkm_vm *vm;
329 u32 fpde, lpde;
330
331 if (unlikely(vma->node == NULL))
332 return;
333 vm = vma->vm;
334 mmu = vm->mmu;
335
336 fpde = (vma->node->offset >> mmu->func->pgt_bits);
337 lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits;
338
339 mutex_lock(&vm->mutex);
340 nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->func->spg_shift, fpde, lpde);
341 nvkm_mm_free(&vm->mm, &vma->node);
342 mutex_unlock(&vm->mutex);
343
344 nvkm_vm_ref(NULL, &vma->vm, NULL);
345}
346
347int
348nvkm_vm_boot(struct nvkm_vm *vm, u64 size)
349{ 221{
350 struct nvkm_mmu *mmu = vm->mmu; 222 struct nvkm_mmu_ptc *ptc;
351 struct nvkm_memory *pgt; 223 list_for_each_entry(ptc, &mmu->ptc.list, head) {
352 int ret; 224 struct nvkm_mmu_pt *pt, *tt;
353 225 list_for_each_entry_safe(pt, tt, &ptc->item, head) {
354 ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, 226 nvkm_memory_unref(&pt->memory);
355 (size >> mmu->func->spg_shift) * 8, 0x1000, true, &pgt); 227 list_del(&pt->head);
356 if (ret == 0) { 228 kfree(pt);
357 vm->pgt[0].refcount[0] = 1; 229 }
358 vm->pgt[0].mem[0] = pgt;
359 nvkm_memory_boot(pgt, vm);
360 } 230 }
361
362 return ret;
363} 231}
364 232
365int 233static void
366nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, 234nvkm_mmu_ptc_fini(struct nvkm_mmu *mmu)
367 u32 block, struct lock_class_key *key, struct nvkm_vm **pvm)
368{ 235{
369 static struct lock_class_key _key; 236 struct nvkm_mmu_ptc *ptc, *ptct;
370 struct nvkm_vm *vm;
371 u64 mm_length = (offset + length) - mm_offset;
372 int ret;
373
374 vm = kzalloc(sizeof(*vm), GFP_KERNEL);
375 if (!vm)
376 return -ENOMEM;
377 237
378 __mutex_init(&vm->mutex, "&vm->mutex", key ? key : &_key); 238 list_for_each_entry_safe(ptc, ptct, &mmu->ptc.list, head) {
379 INIT_LIST_HEAD(&vm->pgd_list); 239 WARN_ON(!list_empty(&ptc->item));
380 vm->mmu = mmu; 240 list_del(&ptc->head);
381 kref_init(&vm->refcount); 241 kfree(ptc);
382 vm->fpde = offset >> (mmu->func->pgt_bits + 12);
383 vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12);
384
385 vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt));
386 if (!vm->pgt) {
387 kfree(vm);
388 return -ENOMEM;
389 } 242 }
390
391 ret = nvkm_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
392 block >> 12);
393 if (ret) {
394 vfree(vm->pgt);
395 kfree(vm);
396 return ret;
397 }
398
399 *pvm = vm;
400
401 return 0;
402} 243}
403 244
404int 245static void
405nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset, 246nvkm_mmu_ptc_init(struct nvkm_mmu *mmu)
406 struct lock_class_key *key, struct nvkm_vm **pvm)
407{ 247{
408 struct nvkm_mmu *mmu = device->mmu; 248 mutex_init(&mmu->ptc.mutex);
409 if (!mmu->func->create) 249 INIT_LIST_HEAD(&mmu->ptc.list);
410 return -EINVAL; 250 mutex_init(&mmu->ptp.mutex);
411 return mmu->func->create(mmu, offset, length, mm_offset, key, pvm); 251 INIT_LIST_HEAD(&mmu->ptp.list);
412} 252}
413 253
414static int 254static void
415nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd) 255nvkm_mmu_type(struct nvkm_mmu *mmu, int heap, u8 type)
416{ 256{
417 struct nvkm_mmu *mmu = vm->mmu; 257 if (heap >= 0 && !WARN_ON(mmu->type_nr == ARRAY_SIZE(mmu->type))) {
418 struct nvkm_vm_pgd *vpgd; 258 mmu->type[mmu->type_nr].type = type | mmu->heap[heap].type;
419 int i; 259 mmu->type[mmu->type_nr].heap = heap;
420 260 mmu->type_nr++;
421 if (!pgd) 261 }
422 return 0;
423
424 vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL);
425 if (!vpgd)
426 return -ENOMEM;
427
428 vpgd->obj = pgd;
429
430 mutex_lock(&vm->mutex);
431 for (i = vm->fpde; i <= vm->lpde; i++)
432 mmu->func->map_pgt(pgd, i, vm->pgt[i - vm->fpde].mem);
433 list_add(&vpgd->head, &vm->pgd_list);
434 mutex_unlock(&vm->mutex);
435 return 0;
436} 262}
437 263
438static void 264static int
439nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd) 265nvkm_mmu_heap(struct nvkm_mmu *mmu, u8 type, u64 size)
440{ 266{
441 struct nvkm_vm_pgd *vpgd, *tmp; 267 if (size) {
442 268 if (!WARN_ON(mmu->heap_nr == ARRAY_SIZE(mmu->heap))) {
443 if (!mpgd) 269 mmu->heap[mmu->heap_nr].type = type;
444 return; 270 mmu->heap[mmu->heap_nr].size = size;
445 271 return mmu->heap_nr++;
446 mutex_lock(&vm->mutex);
447 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
448 if (vpgd->obj == mpgd) {
449 list_del(&vpgd->head);
450 kfree(vpgd);
451 break;
452 } 272 }
453 } 273 }
454 mutex_unlock(&vm->mutex); 274 return -EINVAL;
455} 275}
456 276
457static void 277static void
458nvkm_vm_del(struct kref *kref) 278nvkm_mmu_host(struct nvkm_mmu *mmu)
459{ 279{
460 struct nvkm_vm *vm = container_of(kref, typeof(*vm), refcount); 280 struct nvkm_device *device = mmu->subdev.device;
461 struct nvkm_vm_pgd *vpgd, *tmp; 281 u8 type = NVKM_MEM_KIND * !!mmu->func->kind_sys;
462 282 int heap;
463 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { 283
464 nvkm_vm_unlink(vm, vpgd->obj); 284 /* Non-mappable system memory. */
465 } 285 heap = nvkm_mmu_heap(mmu, NVKM_MEM_HOST, ~0ULL);
466 286 nvkm_mmu_type(mmu, heap, type);
467 nvkm_mm_fini(&vm->mm); 287
468 vfree(vm->pgt); 288 /* Non-coherent, cached, system memory.
469 kfree(vm); 289 *
290 * Block-linear mappings of system memory must be done through
291 * BAR1, and cannot be supported on systems where we're unable
292 * to map BAR1 with write-combining.
293 */
294 type |= NVKM_MEM_MAPPABLE;
295 if (!device->bar || device->bar->iomap_uncached)
296 nvkm_mmu_type(mmu, heap, type & ~NVKM_MEM_KIND);
297 else
298 nvkm_mmu_type(mmu, heap, type);
299
300 /* Coherent, cached, system memory.
301 *
302 * Unsupported on systems that aren't able to support snooped
303 * mappings, and also for block-linear mappings which must be
304 * done through BAR1.
305 */
306 type |= NVKM_MEM_COHERENT;
307 if (device->func->cpu_coherent)
308 nvkm_mmu_type(mmu, heap, type & ~NVKM_MEM_KIND);
309
310 /* Uncached system memory. */
311 nvkm_mmu_type(mmu, heap, type |= NVKM_MEM_UNCACHED);
470} 312}
471 313
472int 314static void
473nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd) 315nvkm_mmu_vram(struct nvkm_mmu *mmu)
474{ 316{
475 if (ref) { 317 struct nvkm_device *device = mmu->subdev.device;
476 int ret = nvkm_vm_link(ref, pgd); 318 struct nvkm_mm *mm = &device->fb->ram->vram;
477 if (ret) 319 const u32 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL);
478 return ret; 320 const u32 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP);
479 321 const u32 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED);
480 kref_get(&ref->refcount); 322 u8 type = NVKM_MEM_KIND * !!mmu->func->kind;
481 } 323 u8 heap = NVKM_MEM_VRAM;
324 int heapM, heapN, heapU;
325
326 /* Mixed-memory doesn't support compression or display. */
327 heapM = nvkm_mmu_heap(mmu, heap, sizeM << NVKM_RAM_MM_SHIFT);
328
329 heap |= NVKM_MEM_COMP;
330 heap |= NVKM_MEM_DISP;
331 heapN = nvkm_mmu_heap(mmu, heap, sizeN << NVKM_RAM_MM_SHIFT);
332 heapU = nvkm_mmu_heap(mmu, heap, sizeU << NVKM_RAM_MM_SHIFT);
333
334 /* Add non-mappable VRAM types first so that they're preferred
335 * over anything else. Mixed-memory will be slower than other
336 * heaps, it's prioritised last.
337 */
338 nvkm_mmu_type(mmu, heapU, type);
339 nvkm_mmu_type(mmu, heapN, type);
340 nvkm_mmu_type(mmu, heapM, type);
341
342 /* Add host memory types next, under the assumption that users
343 * wanting mappable memory want to use them as staging buffers
344 * or the like.
345 */
346 nvkm_mmu_host(mmu);
347
348 /* Mappable VRAM types go last, as they're basically the worst
349 * possible type to ask for unless there's no other choice.
350 */
351 if (device->bar) {
352 /* Write-combined BAR1 access. */
353 type |= NVKM_MEM_MAPPABLE;
354 if (!device->bar->iomap_uncached) {
355 nvkm_mmu_type(mmu, heapN, type);
356 nvkm_mmu_type(mmu, heapM, type);
357 }
482 358
483 if (*ptr) { 359 /* Uncached BAR1 access. */
484 nvkm_vm_unlink(*ptr, pgd); 360 type |= NVKM_MEM_COHERENT;
485 kref_put(&(*ptr)->refcount, nvkm_vm_del); 361 type |= NVKM_MEM_UNCACHED;
362 nvkm_mmu_type(mmu, heapN, type);
363 nvkm_mmu_type(mmu, heapM, type);
486 } 364 }
487
488 *ptr = ref;
489 return 0;
490} 365}
491 366
492static int 367static int
493nvkm_mmu_oneinit(struct nvkm_subdev *subdev) 368nvkm_mmu_oneinit(struct nvkm_subdev *subdev)
494{ 369{
495 struct nvkm_mmu *mmu = nvkm_mmu(subdev); 370 struct nvkm_mmu *mmu = nvkm_mmu(subdev);
496 if (mmu->func->oneinit) 371
497 return mmu->func->oneinit(mmu); 372 /* Determine available memory types. */
373 if (mmu->subdev.device->fb && mmu->subdev.device->fb->ram)
374 nvkm_mmu_vram(mmu);
375 else
376 nvkm_mmu_host(mmu);
377
378 if (mmu->func->vmm.global) {
379 int ret = nvkm_vmm_new(subdev->device, 0, 0, NULL, 0, NULL,
380 "gart", &mmu->vmm);
381 if (ret)
382 return ret;
383 }
384
498 return 0; 385 return 0;
499} 386}
500 387
@@ -511,8 +398,10 @@ static void *
511nvkm_mmu_dtor(struct nvkm_subdev *subdev) 398nvkm_mmu_dtor(struct nvkm_subdev *subdev)
512{ 399{
513 struct nvkm_mmu *mmu = nvkm_mmu(subdev); 400 struct nvkm_mmu *mmu = nvkm_mmu(subdev);
514 if (mmu->func->dtor) 401
515 return mmu->func->dtor(mmu); 402 nvkm_vmm_unref(&mmu->vmm);
403
404 nvkm_mmu_ptc_fini(mmu);
516 return mmu; 405 return mmu;
517} 406}
518 407
@@ -529,9 +418,10 @@ nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device,
529{ 418{
530 nvkm_subdev_ctor(&nvkm_mmu, device, index, &mmu->subdev); 419 nvkm_subdev_ctor(&nvkm_mmu, device, index, &mmu->subdev);
531 mmu->func = func; 420 mmu->func = func;
532 mmu->limit = func->limit;
533 mmu->dma_bits = func->dma_bits; 421 mmu->dma_bits = func->dma_bits;
534 mmu->lpg_shift = func->lpg_shift; 422 nvkm_mmu_ptc_init(mmu);
423 mmu->user.ctor = nvkm_ummu_new;
424 mmu->user.base = func->mmu.user;
535} 425}
536 426
537int 427int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c
new file mode 100644
index 000000000000..8accda5a772b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <nvif/class.h>
26
27static const struct nvkm_mmu_func
28g84_mmu = {
29 .dma_bits = 40,
30 .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV50}},
31 .mem = {{ -1, 0, NVIF_CLASS_MEM_NV50}, nv50_mem_new, nv50_mem_map },
32 .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV50}, nv50_vmm_new, false, 0x0200 },
33 .kind = nv50_mmu_kind,
34 .kind_sys = true,
35};
36
37int
38g84_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
39{
40 return nvkm_mmu_new_(&g84_mmu, device, index, pmmu);
41}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
index 7ac507c927bb..2d075246dc46 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
@@ -21,197 +21,65 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "priv.h" 24#include "mem.h"
25#include "vmm.h"
25 26
26#include <subdev/fb.h> 27#include <nvif/class.h>
27#include <subdev/ltc.h>
28#include <subdev/timer.h>
29
30#include <core/gpuobj.h>
31 28
32/* Map from compressed to corresponding uncompressed storage type. 29/* Map from compressed to corresponding uncompressed storage type.
33 * The value 0xff represents an invalid storage type. 30 * The value 0xff represents an invalid storage type.
34 */ 31 */
35const u8 gf100_pte_storage_type_map[256] = 32const u8 *
36{ 33gf100_mmu_kind(struct nvkm_mmu *mmu, int *count)
37 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */
38 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */
40 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */
42 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */
44 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27,
45 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */
46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */
48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */
52 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff,
53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */
54 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */
58 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
61 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
62 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3,
63 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
64 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe,
65 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */
66 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff,
67 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */
68 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
69};
70
71
72static void
73gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_memory *pgt[2])
74{
75 u32 pde[2] = { 0, 0 };
76
77 if (pgt[0])
78 pde[1] = 0x00000001 | (nvkm_memory_addr(pgt[0]) >> 8);
79 if (pgt[1])
80 pde[0] = 0x00000001 | (nvkm_memory_addr(pgt[1]) >> 8);
81
82 nvkm_kmap(pgd);
83 nvkm_wo32(pgd, (index * 8) + 0, pde[0]);
84 nvkm_wo32(pgd, (index * 8) + 4, pde[1]);
85 nvkm_done(pgd);
86}
87
88static inline u64
89gf100_vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target)
90{
91 phys >>= 8;
92
93 phys |= 0x00000001; /* present */
94 if (vma->access & NV_MEM_ACCESS_SYS)
95 phys |= 0x00000002;
96
97 phys |= ((u64)target << 32);
98 phys |= ((u64)memtype << 36);
99 return phys;
100}
101
102static void
103gf100_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt,
104 struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
105{
106 u64 next = 1 << (vma->node->type - 8);
107
108 phys = gf100_vm_addr(vma, phys, mem->memtype, 0);
109 pte <<= 3;
110
111 if (mem->tag) {
112 struct nvkm_ltc *ltc = vma->vm->mmu->subdev.device->ltc;
113 u32 tag = mem->tag->offset + (delta >> 17);
114 phys |= (u64)tag << (32 + 12);
115 next |= (u64)1 << (32 + 12);
116 nvkm_ltc_tags_clear(ltc, tag, cnt);
117 }
118
119 nvkm_kmap(pgt);
120 while (cnt--) {
121 nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
122 nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
123 phys += next;
124 pte += 8;
125 }
126 nvkm_done(pgt);
127}
128
129static void
130gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
131 struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
132{
133 u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5;
134 /* compressed storage types are invalid for system memory */
135 u32 memtype = gf100_pte_storage_type_map[mem->memtype & 0xff];
136
137 nvkm_kmap(pgt);
138 pte <<= 3;
139 while (cnt--) {
140 u64 phys = gf100_vm_addr(vma, *list++, memtype, target);
141 nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
142 nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
143 pte += 8;
144 }
145 nvkm_done(pgt);
146}
147
148static void
149gf100_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
150{
151 nvkm_kmap(pgt);
152 pte <<= 3;
153 while (cnt--) {
154 nvkm_wo32(pgt, pte + 0, 0x00000000);
155 nvkm_wo32(pgt, pte + 4, 0x00000000);
156 pte += 8;
157 }
158 nvkm_done(pgt);
159}
160
161static void
162gf100_vm_flush(struct nvkm_vm *vm)
163{
164 struct nvkm_mmu *mmu = vm->mmu;
165 struct nvkm_device *device = mmu->subdev.device;
166 struct nvkm_vm_pgd *vpgd;
167 u32 type;
168
169 type = 0x00000001; /* PAGE_ALL */
170 if (atomic_read(&vm->engref[NVKM_SUBDEV_BAR]))
171 type |= 0x00000004; /* HUB_ONLY */
172
173 mutex_lock(&mmu->subdev.mutex);
174 list_for_each_entry(vpgd, &vm->pgd_list, head) {
175 /* looks like maybe a "free flush slots" counter, the
176 * faster you write to 0x100cbc to more it decreases
177 */
178 nvkm_msec(device, 2000,
179 if (nvkm_rd32(device, 0x100c80) & 0x00ff0000)
180 break;
181 );
182
183 nvkm_wr32(device, 0x100cb8, vpgd->obj->addr >> 8);
184 nvkm_wr32(device, 0x100cbc, 0x80000000 | type);
185
186 /* wait for flush to be queued? */
187 nvkm_msec(device, 2000,
188 if (nvkm_rd32(device, 0x100c80) & 0x00008000)
189 break;
190 );
191 }
192 mutex_unlock(&mmu->subdev.mutex);
193}
194
195static int
196gf100_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
197 struct lock_class_key *key, struct nvkm_vm **pvm)
198{ 34{
199 return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, key, pvm); 35 static const u8
36 kind[256] = {
37 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */
38 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */
40 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */
42 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */
44 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27,
45 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */
46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */
48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */
52 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff,
53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */
54 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */
58 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
61 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
62 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3,
63 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
64 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe,
65 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */
66 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff,
67 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */
68 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
69 };
70
71 *count = ARRAY_SIZE(kind);
72 return kind;
200} 73}
201 74
202static const struct nvkm_mmu_func 75static const struct nvkm_mmu_func
203gf100_mmu = { 76gf100_mmu = {
204 .limit = (1ULL << 40),
205 .dma_bits = 40, 77 .dma_bits = 40,
206 .pgt_bits = 27 - 12, 78 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
207 .spg_shift = 12, 79 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
208 .lpg_shift = 17, 80 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gf100_vmm_new },
209 .create = gf100_vm_create, 81 .kind = gf100_mmu_kind,
210 .map_pgt = gf100_vm_map_pgt, 82 .kind_sys = true,
211 .map = gf100_vm_map,
212 .map_sg = gf100_vm_map_sg,
213 .unmap = gf100_vm_unmap,
214 .flush = gf100_vm_flush,
215}; 83};
216 84
217int 85int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c
new file mode 100644
index 000000000000..3d7d1eb1cff9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <nvif/class.h>
26
27static const struct nvkm_mmu_func
28gk104_mmu = {
29 .dma_bits = 40,
30 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
31 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
32 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gk104_vmm_new },
33 .kind = gf100_mmu_kind,
34 .kind_sys = true,
35};
36
37int
38gk104_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
39{
40 return nvkm_mmu_new_(&gk104_mmu, device, index, pmmu);
41}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c
new file mode 100644
index 000000000000..ac74965a60d4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <nvif/class.h>
26
27static const struct nvkm_mmu_func
28gk20a_mmu = {
29 .dma_bits = 40,
30 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
31 .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map },
32 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gk20a_vmm_new },
33 .kind = gf100_mmu_kind,
34 .kind_sys = true,
35};
36
37int
38gk20a_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
39{
40 return nvkm_mmu_new_(&gk20a_mmu, device, index, pmmu);
41}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
new file mode 100644
index 000000000000..dbf644ebac97
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
@@ -0,0 +1,97 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <subdev/fb.h>
26
27#include <nvif/class.h>
28
29const u8 *
30gm200_mmu_kind(struct nvkm_mmu *mmu, int *count)
31{
32 static const u8
33 kind[256] = {
34 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */
35 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
36 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */
37 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */
39 0x28, 0x29, 0x2a, 0x2b, 0xff, 0xff, 0xff, 0xff,
40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */
41 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27,
42 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */
47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */
49 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */
51 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff,
52 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */
55 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff,
56 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7,
58 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
59 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3,
60 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
61 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe,
62 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */
63 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff,
64 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */
65 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
66 };
67 *count = ARRAY_SIZE(kind);
68 return kind;
69}
70
71static const struct nvkm_mmu_func
72gm200_mmu = {
73 .dma_bits = 40,
74 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
75 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
76 .vmm = {{ -1, 0, NVIF_CLASS_VMM_GM200}, gm200_vmm_new },
77 .kind = gm200_mmu_kind,
78 .kind_sys = true,
79};
80
81static const struct nvkm_mmu_func
82gm200_mmu_fixed = {
83 .dma_bits = 40,
84 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
85 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
86 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GM200}, gm200_vmm_new_fixed },
87 .kind = gm200_mmu_kind,
88 .kind_sys = true,
89};
90
91int
92gm200_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
93{
94 if (device->fb->page)
95 return nvkm_mmu_new_(&gm200_mmu_fixed, device, index, pmmu);
96 return nvkm_mmu_new_(&gm200_mmu, device, index, pmmu);
97}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c
new file mode 100644
index 000000000000..7353a94b4091
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <subdev/fb.h>
26
27#include <nvif/class.h>
28
29static const struct nvkm_mmu_func
30gm20b_mmu = {
31 .dma_bits = 40,
32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
33 .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map },
34 .vmm = {{ -1, 0, NVIF_CLASS_VMM_GM200}, gm20b_vmm_new },
35 .kind = gm200_mmu_kind,
36 .kind_sys = true,
37};
38
39static const struct nvkm_mmu_func
40gm20b_mmu_fixed = {
41 .dma_bits = 40,
42 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
43 .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map },
44 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GM200}, gm20b_vmm_new_fixed },
45 .kind = gm200_mmu_kind,
46 .kind_sys = true,
47};
48
49int
50gm20b_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
51{
52 if (device->fb->page)
53 return nvkm_mmu_new_(&gm20b_mmu_fixed, device, index, pmmu);
54 return nvkm_mmu_new_(&gm20b_mmu, device, index, pmmu);
55}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c
new file mode 100644
index 000000000000..651b8805c67c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <core/option.h>
26
27#include <nvif/class.h>
28
29static const struct nvkm_mmu_func
30gp100_mmu = {
31 .dma_bits = 47,
32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
33 .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
34 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp100_vmm_new },
35 .kind = gm200_mmu_kind,
36 .kind_sys = true,
37};
38
39int
40gp100_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
41{
42 if (!nvkm_boolopt(device->cfgopt, "GP100MmuLayout", true))
43 return gm200_mmu_new(device, index, pmmu);
44 return nvkm_mmu_new_(&gp100_mmu, device, index, pmmu);
45}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b. b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c
new file mode 100644
index 000000000000..3bd3db31e0bb
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23#include "vmm.h"
24
25#include <core/option.h>
26
27#include <nvif/class.h>
28
29static const struct nvkm_mmu_func
30gp10b_mmu = {
31 .dma_bits = 47,
32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
33 .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map },
34 .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new },
35 .kind = gm200_mmu_kind,
36 .kind_sys = true,
37};
38
39int
40gp10b_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
41{
42 if (!nvkm_boolopt(device->cfgopt, "GP100MmuLayout", true))
43 return gm20b_mmu_new(device, index, pmmu);
44 return nvkm_mmu_new_(&gp10b_mmu, device, index, pmmu);
45}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c
new file mode 100644
index 000000000000..39808489f21d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c
@@ -0,0 +1,242 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#define nvkm_mem(p) container_of((p), struct nvkm_mem, memory)
23#include "mem.h"
24
25#include <core/memory.h>
26
27#include <nvif/if000a.h>
28#include <nvif/unpack.h>
29
30struct nvkm_mem {
31 struct nvkm_memory memory;
32 enum nvkm_memory_target target;
33 struct nvkm_mmu *mmu;
34 u64 pages;
35 struct page **mem;
36 union {
37 struct scatterlist *sgl;
38 dma_addr_t *dma;
39 };
40};
41
42static enum nvkm_memory_target
43nvkm_mem_target(struct nvkm_memory *memory)
44{
45 return nvkm_mem(memory)->target;
46}
47
48static u8
49nvkm_mem_page(struct nvkm_memory *memory)
50{
51 return PAGE_SHIFT;
52}
53
54static u64
55nvkm_mem_addr(struct nvkm_memory *memory)
56{
57 struct nvkm_mem *mem = nvkm_mem(memory);
58 if (mem->pages == 1 && mem->mem)
59 return mem->dma[0];
60 return ~0ULL;
61}
62
63static u64
64nvkm_mem_size(struct nvkm_memory *memory)
65{
66 return nvkm_mem(memory)->pages << PAGE_SHIFT;
67}
68
69static int
70nvkm_mem_map_dma(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
71 struct nvkm_vma *vma, void *argv, u32 argc)
72{
73 struct nvkm_mem *mem = nvkm_mem(memory);
74 struct nvkm_vmm_map map = {
75 .memory = &mem->memory,
76 .offset = offset,
77 .dma = mem->dma,
78 };
79 return nvkm_vmm_map(vmm, vma, argv, argc, &map);
80}
81
82static void *
83nvkm_mem_dtor(struct nvkm_memory *memory)
84{
85 struct nvkm_mem *mem = nvkm_mem(memory);
86 if (mem->mem) {
87 while (mem->pages--) {
88 dma_unmap_page(mem->mmu->subdev.device->dev,
89 mem->dma[mem->pages], PAGE_SIZE,
90 DMA_BIDIRECTIONAL);
91 __free_page(mem->mem[mem->pages]);
92 }
93 kvfree(mem->dma);
94 kvfree(mem->mem);
95 }
96 return mem;
97}
98
99static const struct nvkm_memory_func
100nvkm_mem_dma = {
101 .dtor = nvkm_mem_dtor,
102 .target = nvkm_mem_target,
103 .page = nvkm_mem_page,
104 .addr = nvkm_mem_addr,
105 .size = nvkm_mem_size,
106 .map = nvkm_mem_map_dma,
107};
108
109static int
110nvkm_mem_map_sgl(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
111 struct nvkm_vma *vma, void *argv, u32 argc)
112{
113 struct nvkm_mem *mem = nvkm_mem(memory);
114 struct nvkm_vmm_map map = {
115 .memory = &mem->memory,
116 .offset = offset,
117 .sgl = mem->sgl,
118 };
119 return nvkm_vmm_map(vmm, vma, argv, argc, &map);
120}
121
122static const struct nvkm_memory_func
123nvkm_mem_sgl = {
124 .dtor = nvkm_mem_dtor,
125 .target = nvkm_mem_target,
126 .page = nvkm_mem_page,
127 .addr = nvkm_mem_addr,
128 .size = nvkm_mem_size,
129 .map = nvkm_mem_map_sgl,
130};
131
132int
133nvkm_mem_map_host(struct nvkm_memory *memory, void **pmap)
134{
135 struct nvkm_mem *mem = nvkm_mem(memory);
136 if (mem->mem) {
137 *pmap = vmap(mem->mem, mem->pages, VM_MAP, PAGE_KERNEL);
138 return *pmap ? 0 : -EFAULT;
139 }
140 return -EINVAL;
141}
142
143static int
144nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
145 void *argv, u32 argc, struct nvkm_memory **pmemory)
146{
147 struct device *dev = mmu->subdev.device->dev;
148 union {
149 struct nvif_mem_ram_vn vn;
150 struct nvif_mem_ram_v0 v0;
151 } *args = argv;
152 int ret = -ENOSYS;
153 enum nvkm_memory_target target;
154 struct nvkm_mem *mem;
155 gfp_t gfp = GFP_USER | __GFP_ZERO;
156
157 if ( (mmu->type[type].type & NVKM_MEM_COHERENT) &&
158 !(mmu->type[type].type & NVKM_MEM_UNCACHED))
159 target = NVKM_MEM_TARGET_HOST;
160 else
161 target = NVKM_MEM_TARGET_NCOH;
162
163 if (page != PAGE_SHIFT)
164 return -EINVAL;
165
166 if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL)))
167 return -ENOMEM;
168 mem->target = target;
169 mem->mmu = mmu;
170 *pmemory = &mem->memory;
171
172 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
173 if (args->v0.dma) {
174 nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory);
175 mem->dma = args->v0.dma;
176 } else {
177 nvkm_memory_ctor(&nvkm_mem_sgl, &mem->memory);
178 mem->sgl = args->v0.sgl;
179 }
180
181 if (!IS_ALIGNED(size, PAGE_SIZE))
182 return -EINVAL;
183 mem->pages = size >> PAGE_SHIFT;
184 return 0;
185 } else
186 if ( (ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
187 kfree(mem);
188 return ret;
189 }
190
191 nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory);
192 size = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT;
193
194 if (!(mem->mem = kvmalloc(sizeof(*mem->mem) * size, GFP_KERNEL)))
195 return -ENOMEM;
196 if (!(mem->dma = kvmalloc(sizeof(*mem->dma) * size, GFP_KERNEL)))
197 return -ENOMEM;
198
199 if (mmu->dma_bits > 32)
200 gfp |= GFP_HIGHUSER;
201 else
202 gfp |= GFP_DMA32;
203
204 for (mem->pages = 0; size; size--, mem->pages++) {
205 struct page *p = alloc_page(gfp);
206 if (!p)
207 return -ENOMEM;
208
209 mem->dma[mem->pages] = dma_map_page(mmu->subdev.device->dev,
210 p, 0, PAGE_SIZE,
211 DMA_BIDIRECTIONAL);
212 if (dma_mapping_error(dev, mem->dma[mem->pages])) {
213 __free_page(p);
214 return -ENOMEM;
215 }
216
217 mem->mem[mem->pages] = p;
218 }
219
220 return 0;
221}
222
223int
224nvkm_mem_new_type(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
225 void *argv, u32 argc, struct nvkm_memory **pmemory)
226{
227 struct nvkm_memory *memory = NULL;
228 int ret;
229
230 if (mmu->type[type].type & NVKM_MEM_VRAM) {
231 ret = mmu->func->mem.vram(mmu, type, page, size,
232 argv, argc, &memory);
233 } else {
234 ret = nvkm_mem_new_host(mmu, type, page, size,
235 argv, argc, &memory);
236 }
237
238 if (ret)
239 nvkm_memory_unref(&memory);
240 *pmemory = memory;
241 return ret;
242}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h
new file mode 100644
index 000000000000..234267e1b215
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h
@@ -0,0 +1,23 @@
1#ifndef __NVKM_MEM_H__
2#define __NVKM_MEM_H__
3#include "priv.h"
4
5int nvkm_mem_new_type(struct nvkm_mmu *, int type, u8 page, u64 size,
6 void *argv, u32 argc, struct nvkm_memory **);
7int nvkm_mem_map_host(struct nvkm_memory *, void **pmap);
8
9int nv04_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32,
10 struct nvkm_memory **);
11int nv04_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32,
12 u64 *, u64 *, struct nvkm_vma **);
13
14int nv50_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32,
15 struct nvkm_memory **);
16int nv50_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32,
17 u64 *, u64 *, struct nvkm_vma **);
18
19int gf100_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32,
20 struct nvkm_memory **);
21int gf100_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32,
22 u64 *, u64 *, struct nvkm_vma **);
23#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c
new file mode 100644
index 000000000000..d9c9bee45222
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c
@@ -0,0 +1,94 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23
24#include <core/memory.h>
25#include <subdev/bar.h>
26#include <subdev/fb.h>
27
28#include <nvif/class.h>
29#include <nvif/if900b.h>
30#include <nvif/if900d.h>
31#include <nvif/unpack.h>
32
33int
34gf100_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv,
35 u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma)
36{
37 struct gf100_vmm_map_v0 uvmm = {};
38 union {
39 struct gf100_mem_map_vn vn;
40 struct gf100_mem_map_v0 v0;
41 } *args = argv;
42 struct nvkm_device *device = mmu->subdev.device;
43 struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
44 int ret = -ENOSYS;
45
46 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
47 uvmm.ro = args->v0.ro;
48 uvmm.kind = args->v0.kind;
49 } else
50 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
51 } else
52 return ret;
53
54 ret = nvkm_vmm_get(bar, nvkm_memory_page(memory),
55 nvkm_memory_size(memory), pvma);
56 if (ret)
57 return ret;
58
59 ret = nvkm_memory_map(memory, 0, bar, *pvma, &uvmm, sizeof(uvmm));
60 if (ret)
61 return ret;
62
63 *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr;
64 *psize = (*pvma)->size;
65 return 0;
66}
67
68int
69gf100_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
70 void *argv, u32 argc, struct nvkm_memory **pmemory)
71{
72 union {
73 struct gf100_mem_vn vn;
74 struct gf100_mem_v0 v0;
75 } *args = argv;
76 int ret = -ENOSYS;
77 bool contig;
78
79 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
80 contig = args->v0.contig;
81 } else
82 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
83 contig = false;
84 } else
85 return ret;
86
87 if (mmu->type[type].type & (NVKM_MEM_DISP | NVKM_MEM_COMP))
88 type = NVKM_RAM_MM_NORMAL;
89 else
90 type = NVKM_RAM_MM_MIXED;
91
92 return nvkm_ram_get(mmu->subdev.device, type, 0x01, page,
93 size, contig, false, pmemory);
94}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c
new file mode 100644
index 000000000000..79a3b0cc9f5b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c
@@ -0,0 +1,69 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23
24#include <core/memory.h>
25#include <subdev/fb.h>
26
27#include <nvif/if000b.h>
28#include <nvif/unpack.h>
29
30int
31nv04_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv,
32 u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma)
33{
34 union {
35 struct nv04_mem_map_vn vn;
36 } *args = argv;
37 struct nvkm_device *device = mmu->subdev.device;
38 const u64 addr = nvkm_memory_addr(memory);
39 int ret = -ENOSYS;
40
41 if ((ret = nvif_unvers(ret, &argv, &argc, args->vn)))
42 return ret;
43
44 *paddr = device->func->resource_addr(device, 1) + addr;
45 *psize = nvkm_memory_size(memory);
46 *pvma = ERR_PTR(-ENODEV);
47 return 0;
48}
49
50int
51nv04_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
52 void *argv, u32 argc, struct nvkm_memory **pmemory)
53{
54 union {
55 struct nv04_mem_vn vn;
56 } *args = argv;
57 int ret = -ENOSYS;
58
59 if ((ret = nvif_unvers(ret, &argv, &argc, args->vn)))
60 return ret;
61
62 if (mmu->type[type].type & NVKM_MEM_MAPPABLE)
63 type = NVKM_RAM_MM_NORMAL;
64 else
65 type = NVKM_RAM_MM_NOMAP;
66
67 return nvkm_ram_get(mmu->subdev.device, type, 0x01, page,
68 size, true, false, pmemory);
69}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c
new file mode 100644
index 000000000000..46759b89fc1f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "mem.h"
23
24#include <core/memory.h>
25#include <subdev/bar.h>
26#include <subdev/fb.h>
27
28#include <nvif/class.h>
29#include <nvif/if500b.h>
30#include <nvif/if500d.h>
31#include <nvif/unpack.h>
32
33int
34nv50_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv,
35 u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma)
36{
37 struct nv50_vmm_map_v0 uvmm = {};
38 union {
39 struct nv50_mem_map_vn vn;
40 struct nv50_mem_map_v0 v0;
41 } *args = argv;
42 struct nvkm_device *device = mmu->subdev.device;
43 struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
44 u64 size = nvkm_memory_size(memory);
45 int ret = -ENOSYS;
46
47 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
48 uvmm.ro = args->v0.ro;
49 uvmm.kind = args->v0.kind;
50 uvmm.comp = args->v0.comp;
51 } else
52 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
53 } else
54 return ret;
55
56 ret = nvkm_vmm_get(bar, 12, size, pvma);
57 if (ret)
58 return ret;
59
60 *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr;
61 *psize = (*pvma)->size;
62 return nvkm_memory_map(memory, 0, bar, *pvma, &uvmm, sizeof(uvmm));
63}
64
65int
66nv50_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
67 void *argv, u32 argc, struct nvkm_memory **pmemory)
68{
69 union {
70 struct nv50_mem_vn vn;
71 struct nv50_mem_v0 v0;
72 } *args = argv;
73 int ret = -ENOSYS;
74 bool contig;
75
76 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
77 type = args->v0.bankswz ? 0x02 : 0x01;
78 contig = args->v0.contig;
79 } else
80 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
81 type = 0x01;
82 contig = false;
83 } else
84 return -ENOSYS;
85
86 return nvkm_ram_get(mmu->subdev.device, NVKM_RAM_MM_NORMAL, type,
87 page, size, contig, false, pmemory);
88}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
index 37927c3fdc3e..d201c887c2cd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c
@@ -21,129 +21,21 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "nv04.h" 24#include "mem.h"
25#include "vmm.h"
25 26
26#include <core/gpuobj.h> 27#include <nvif/class.h>
27
28#define NV04_PDMA_SIZE (128 * 1024 * 1024)
29#define NV04_PDMA_PAGE ( 4 * 1024)
30
31/*******************************************************************************
32 * VM map/unmap callbacks
33 ******************************************************************************/
34
35static void
36nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
37 struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
38{
39 pte = 0x00008 + (pte * 4);
40 nvkm_kmap(pgt);
41 while (cnt) {
42 u32 page = PAGE_SIZE / NV04_PDMA_PAGE;
43 u32 phys = (u32)*list++;
44 while (cnt && page--) {
45 nvkm_wo32(pgt, pte, phys | 3);
46 phys += NV04_PDMA_PAGE;
47 pte += 4;
48 cnt -= 1;
49 }
50 }
51 nvkm_done(pgt);
52}
53
54static void
55nv04_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
56{
57 pte = 0x00008 + (pte * 4);
58 nvkm_kmap(pgt);
59 while (cnt--) {
60 nvkm_wo32(pgt, pte, 0x00000000);
61 pte += 4;
62 }
63 nvkm_done(pgt);
64}
65
66static void
67nv04_vm_flush(struct nvkm_vm *vm)
68{
69}
70
71/*******************************************************************************
72 * MMU subdev
73 ******************************************************************************/
74
75static int
76nv04_mmu_oneinit(struct nvkm_mmu *base)
77{
78 struct nv04_mmu *mmu = nv04_mmu(base);
79 struct nvkm_device *device = mmu->base.subdev.device;
80 struct nvkm_memory *dma;
81 int ret;
82
83 ret = nvkm_vm_create(&mmu->base, 0, NV04_PDMA_SIZE, 0, 4096, NULL,
84 &mmu->vm);
85 if (ret)
86 return ret;
87
88 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
89 (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + 8,
90 16, true, &dma);
91 mmu->vm->pgt[0].mem[0] = dma;
92 mmu->vm->pgt[0].refcount[0] = 1;
93 if (ret)
94 return ret;
95
96 nvkm_kmap(dma);
97 nvkm_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */
98 nvkm_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1);
99 nvkm_done(dma);
100 return 0;
101}
102
103void *
104nv04_mmu_dtor(struct nvkm_mmu *base)
105{
106 struct nv04_mmu *mmu = nv04_mmu(base);
107 struct nvkm_device *device = mmu->base.subdev.device;
108 if (mmu->vm) {
109 nvkm_memory_del(&mmu->vm->pgt[0].mem[0]);
110 nvkm_vm_ref(NULL, &mmu->vm, NULL);
111 }
112 if (mmu->nullp) {
113 dma_free_coherent(device->dev, 16 * 1024,
114 mmu->nullp, mmu->null);
115 }
116 return mmu;
117}
118
119int
120nv04_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device,
121 int index, struct nvkm_mmu **pmmu)
122{
123 struct nv04_mmu *mmu;
124 if (!(mmu = kzalloc(sizeof(*mmu), GFP_KERNEL)))
125 return -ENOMEM;
126 *pmmu = &mmu->base;
127 nvkm_mmu_ctor(func, device, index, &mmu->base);
128 return 0;
129}
130 28
131const struct nvkm_mmu_func 29const struct nvkm_mmu_func
132nv04_mmu = { 30nv04_mmu = {
133 .oneinit = nv04_mmu_oneinit,
134 .dtor = nv04_mmu_dtor,
135 .limit = NV04_PDMA_SIZE,
136 .dma_bits = 32, 31 .dma_bits = 32,
137 .pgt_bits = 32 - 12, 32 .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}},
138 .spg_shift = 12, 33 .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map },
139 .lpg_shift = 12, 34 .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv04_vmm_new, true },
140 .map_sg = nv04_vm_map_sg,
141 .unmap = nv04_vm_unmap,
142 .flush = nv04_vm_flush,
143}; 35};
144 36
145int 37int
146nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) 38nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
147{ 39{
148 return nv04_mmu_new_(&nv04_mmu, device, index, pmmu); 40 return nvkm_mmu_new_(&nv04_mmu, device, index, pmmu);
149} 41}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h
deleted file mode 100644
index 363e33b296d5..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h
+++ /dev/null
@@ -1,18 +0,0 @@
1#ifndef __NV04_MMU_PRIV__
2#define __NV04_MMU_PRIV__
3#define nv04_mmu(p) container_of((p), struct nv04_mmu, base)
4#include "priv.h"
5
6struct nv04_mmu {
7 struct nvkm_mmu base;
8 struct nvkm_vm *vm;
9 dma_addr_t null;
10 void *nullp;
11};
12
13int nv04_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *,
14 int index, struct nvkm_mmu **);
15void *nv04_mmu_dtor(struct nvkm_mmu *);
16
17extern const struct nvkm_mmu_func nv04_mmu;
18#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
index c6a26f907009..adca81895c09 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c
@@ -21,113 +21,29 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "nv04.h" 24#include "mem.h"
25#include "vmm.h"
25 26
26#include <core/gpuobj.h>
27#include <core/option.h> 27#include <core/option.h>
28#include <subdev/timer.h>
29 28
30#define NV41_GART_SIZE (512 * 1024 * 1024) 29#include <nvif/class.h>
31#define NV41_GART_PAGE ( 4 * 1024)
32
33/*******************************************************************************
34 * VM map/unmap callbacks
35 ******************************************************************************/
36
37static void
38nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
39 struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
40{
41 pte = pte * 4;
42 nvkm_kmap(pgt);
43 while (cnt) {
44 u32 page = PAGE_SIZE / NV41_GART_PAGE;
45 u64 phys = (u64)*list++;
46 while (cnt && page--) {
47 nvkm_wo32(pgt, pte, (phys >> 7) | 1);
48 phys += NV41_GART_PAGE;
49 pte += 4;
50 cnt -= 1;
51 }
52 }
53 nvkm_done(pgt);
54}
55
56static void
57nv41_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
58{
59 pte = pte * 4;
60 nvkm_kmap(pgt);
61 while (cnt--) {
62 nvkm_wo32(pgt, pte, 0x00000000);
63 pte += 4;
64 }
65 nvkm_done(pgt);
66}
67
68static void
69nv41_vm_flush(struct nvkm_vm *vm)
70{
71 struct nv04_mmu *mmu = nv04_mmu(vm->mmu);
72 struct nvkm_device *device = mmu->base.subdev.device;
73
74 mutex_lock(&mmu->base.subdev.mutex);
75 nvkm_wr32(device, 0x100810, 0x00000022);
76 nvkm_msec(device, 2000,
77 if (nvkm_rd32(device, 0x100810) & 0x00000020)
78 break;
79 );
80 nvkm_wr32(device, 0x100810, 0x00000000);
81 mutex_unlock(&mmu->base.subdev.mutex);
82}
83
84/*******************************************************************************
85 * MMU subdev
86 ******************************************************************************/
87
88static int
89nv41_mmu_oneinit(struct nvkm_mmu *base)
90{
91 struct nv04_mmu *mmu = nv04_mmu(base);
92 struct nvkm_device *device = mmu->base.subdev.device;
93 int ret;
94
95 ret = nvkm_vm_create(&mmu->base, 0, NV41_GART_SIZE, 0, 4096, NULL,
96 &mmu->vm);
97 if (ret)
98 return ret;
99
100 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
101 (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, true,
102 &mmu->vm->pgt[0].mem[0]);
103 mmu->vm->pgt[0].refcount[0] = 1;
104 return ret;
105}
106 30
107static void 31static void
108nv41_mmu_init(struct nvkm_mmu *base) 32nv41_mmu_init(struct nvkm_mmu *mmu)
109{ 33{
110 struct nv04_mmu *mmu = nv04_mmu(base); 34 struct nvkm_device *device = mmu->subdev.device;
111 struct nvkm_device *device = mmu->base.subdev.device; 35 nvkm_wr32(device, 0x100800, 0x00000002 | mmu->vmm->pd->pt[0]->addr);
112 struct nvkm_memory *dma = mmu->vm->pgt[0].mem[0];
113 nvkm_wr32(device, 0x100800, 0x00000002 | nvkm_memory_addr(dma));
114 nvkm_mask(device, 0x10008c, 0x00000100, 0x00000100); 36 nvkm_mask(device, 0x10008c, 0x00000100, 0x00000100);
115 nvkm_wr32(device, 0x100820, 0x00000000); 37 nvkm_wr32(device, 0x100820, 0x00000000);
116} 38}
117 39
118static const struct nvkm_mmu_func 40static const struct nvkm_mmu_func
119nv41_mmu = { 41nv41_mmu = {
120 .dtor = nv04_mmu_dtor,
121 .oneinit = nv41_mmu_oneinit,
122 .init = nv41_mmu_init, 42 .init = nv41_mmu_init,
123 .limit = NV41_GART_SIZE,
124 .dma_bits = 39, 43 .dma_bits = 39,
125 .pgt_bits = 32 - 12, 44 .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}},
126 .spg_shift = 12, 45 .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map },
127 .lpg_shift = 12, 46 .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv41_vmm_new, true },
128 .map_sg = nv41_vm_map_sg,
129 .unmap = nv41_vm_unmap,
130 .flush = nv41_vm_flush,
131}; 47};
132 48
133int 49int
@@ -137,5 +53,5 @@ nv41_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
137 !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) 53 !nvkm_boolopt(device->cfgopt, "NvPCIE", true))
138 return nv04_mmu_new(device, index, pmmu); 54 return nv04_mmu_new(device, index, pmmu);
139 55
140 return nv04_mmu_new_(&nv41_mmu, device, index, pmmu); 56 return nvkm_mmu_new_(&nv41_mmu, device, index, pmmu);
141} 57}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
index a648c2395545..598c53a27bde 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c
@@ -21,176 +21,18 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "nv04.h" 24#include "mem.h"
25#include "vmm.h"
25 26
26#include <core/gpuobj.h>
27#include <core/option.h> 27#include <core/option.h>
28#include <subdev/timer.h>
29 28
30#define NV44_GART_SIZE (512 * 1024 * 1024) 29#include <nvif/class.h>
31#define NV44_GART_PAGE ( 4 * 1024)
32
33/*******************************************************************************
34 * VM map/unmap callbacks
35 ******************************************************************************/
36
37static void
38nv44_vm_fill(struct nvkm_memory *pgt, dma_addr_t null,
39 dma_addr_t *list, u32 pte, u32 cnt)
40{
41 u32 base = (pte << 2) & ~0x0000000f;
42 u32 tmp[4];
43
44 tmp[0] = nvkm_ro32(pgt, base + 0x0);
45 tmp[1] = nvkm_ro32(pgt, base + 0x4);
46 tmp[2] = nvkm_ro32(pgt, base + 0x8);
47 tmp[3] = nvkm_ro32(pgt, base + 0xc);
48
49 while (cnt--) {
50 u32 addr = list ? (*list++ >> 12) : (null >> 12);
51 switch (pte++ & 0x3) {
52 case 0:
53 tmp[0] &= ~0x07ffffff;
54 tmp[0] |= addr;
55 break;
56 case 1:
57 tmp[0] &= ~0xf8000000;
58 tmp[0] |= addr << 27;
59 tmp[1] &= ~0x003fffff;
60 tmp[1] |= addr >> 5;
61 break;
62 case 2:
63 tmp[1] &= ~0xffc00000;
64 tmp[1] |= addr << 22;
65 tmp[2] &= ~0x0001ffff;
66 tmp[2] |= addr >> 10;
67 break;
68 case 3:
69 tmp[2] &= ~0xfffe0000;
70 tmp[2] |= addr << 17;
71 tmp[3] &= ~0x00000fff;
72 tmp[3] |= addr >> 15;
73 break;
74 }
75 }
76
77 nvkm_wo32(pgt, base + 0x0, tmp[0]);
78 nvkm_wo32(pgt, base + 0x4, tmp[1]);
79 nvkm_wo32(pgt, base + 0x8, tmp[2]);
80 nvkm_wo32(pgt, base + 0xc, tmp[3] | 0x40000000);
81}
82
83static void
84nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
85 struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
86{
87 struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
88 u32 tmp[4];
89 int i;
90
91 nvkm_kmap(pgt);
92 if (pte & 3) {
93 u32 max = 4 - (pte & 3);
94 u32 part = (cnt > max) ? max : cnt;
95 nv44_vm_fill(pgt, mmu->null, list, pte, part);
96 pte += part;
97 list += part;
98 cnt -= part;
99 }
100
101 while (cnt >= 4) {
102 for (i = 0; i < 4; i++)
103 tmp[i] = *list++ >> 12;
104 nvkm_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27);
105 nvkm_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22);
106 nvkm_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17);
107 nvkm_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000);
108 cnt -= 4;
109 }
110
111 if (cnt)
112 nv44_vm_fill(pgt, mmu->null, list, pte, cnt);
113 nvkm_done(pgt);
114}
115
116static void
117nv44_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
118{
119 struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu);
120
121 nvkm_kmap(pgt);
122 if (pte & 3) {
123 u32 max = 4 - (pte & 3);
124 u32 part = (cnt > max) ? max : cnt;
125 nv44_vm_fill(pgt, mmu->null, NULL, pte, part);
126 pte += part;
127 cnt -= part;
128 }
129
130 while (cnt >= 4) {
131 nvkm_wo32(pgt, pte++ * 4, 0x00000000);
132 nvkm_wo32(pgt, pte++ * 4, 0x00000000);
133 nvkm_wo32(pgt, pte++ * 4, 0x00000000);
134 nvkm_wo32(pgt, pte++ * 4, 0x00000000);
135 cnt -= 4;
136 }
137
138 if (cnt)
139 nv44_vm_fill(pgt, mmu->null, NULL, pte, cnt);
140 nvkm_done(pgt);
141}
142
143static void
144nv44_vm_flush(struct nvkm_vm *vm)
145{
146 struct nv04_mmu *mmu = nv04_mmu(vm->mmu);
147 struct nvkm_device *device = mmu->base.subdev.device;
148 nvkm_wr32(device, 0x100814, mmu->base.limit - NV44_GART_PAGE);
149 nvkm_wr32(device, 0x100808, 0x00000020);
150 nvkm_msec(device, 2000,
151 if (nvkm_rd32(device, 0x100808) & 0x00000001)
152 break;
153 );
154 nvkm_wr32(device, 0x100808, 0x00000000);
155}
156
157/*******************************************************************************
158 * MMU subdev
159 ******************************************************************************/
160
161static int
162nv44_mmu_oneinit(struct nvkm_mmu *base)
163{
164 struct nv04_mmu *mmu = nv04_mmu(base);
165 struct nvkm_device *device = mmu->base.subdev.device;
166 int ret;
167
168 mmu->nullp = dma_alloc_coherent(device->dev, 16 * 1024,
169 &mmu->null, GFP_KERNEL);
170 if (!mmu->nullp) {
171 nvkm_warn(&mmu->base.subdev, "unable to allocate dummy pages\n");
172 mmu->null = 0;
173 }
174
175 ret = nvkm_vm_create(&mmu->base, 0, NV44_GART_SIZE, 0, 4096, NULL,
176 &mmu->vm);
177 if (ret)
178 return ret;
179
180 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
181 (NV44_GART_SIZE / NV44_GART_PAGE) * 4,
182 512 * 1024, true,
183 &mmu->vm->pgt[0].mem[0]);
184 mmu->vm->pgt[0].refcount[0] = 1;
185 return ret;
186}
187 30
188static void 31static void
189nv44_mmu_init(struct nvkm_mmu *base) 32nv44_mmu_init(struct nvkm_mmu *mmu)
190{ 33{
191 struct nv04_mmu *mmu = nv04_mmu(base); 34 struct nvkm_device *device = mmu->subdev.device;
192 struct nvkm_device *device = mmu->base.subdev.device; 35 struct nvkm_memory *pt = mmu->vmm->pd->pt[0]->memory;
193 struct nvkm_memory *gart = mmu->vm->pgt[0].mem[0];
194 u32 addr; 36 u32 addr;
195 37
196 /* calculate vram address of this PRAMIN block, object must be 38 /* calculate vram address of this PRAMIN block, object must be
@@ -198,11 +40,11 @@ nv44_mmu_init(struct nvkm_mmu *base)
198 * of 512KiB for this to work correctly 40 * of 512KiB for this to work correctly
199 */ 41 */
200 addr = nvkm_rd32(device, 0x10020c); 42 addr = nvkm_rd32(device, 0x10020c);
201 addr -= ((nvkm_memory_addr(gart) >> 19) + 1) << 19; 43 addr -= ((nvkm_memory_addr(pt) >> 19) + 1) << 19;
202 44
203 nvkm_wr32(device, 0x100850, 0x80000000); 45 nvkm_wr32(device, 0x100850, 0x80000000);
204 nvkm_wr32(device, 0x100818, mmu->null); 46 nvkm_wr32(device, 0x100818, mmu->vmm->null);
205 nvkm_wr32(device, 0x100804, NV44_GART_SIZE); 47 nvkm_wr32(device, 0x100804, (nvkm_memory_size(pt) / 4) * 4096);
206 nvkm_wr32(device, 0x100850, 0x00008000); 48 nvkm_wr32(device, 0x100850, 0x00008000);
207 nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200); 49 nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200);
208 nvkm_wr32(device, 0x100820, 0x00000000); 50 nvkm_wr32(device, 0x100820, 0x00000000);
@@ -212,17 +54,11 @@ nv44_mmu_init(struct nvkm_mmu *base)
212 54
213static const struct nvkm_mmu_func 55static const struct nvkm_mmu_func
214nv44_mmu = { 56nv44_mmu = {
215 .dtor = nv04_mmu_dtor,
216 .oneinit = nv44_mmu_oneinit,
217 .init = nv44_mmu_init, 57 .init = nv44_mmu_init,
218 .limit = NV44_GART_SIZE,
219 .dma_bits = 39, 58 .dma_bits = 39,
220 .pgt_bits = 32 - 12, 59 .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}},
221 .spg_shift = 12, 60 .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map },
222 .lpg_shift = 12, 61 .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv44_vmm_new, true },
223 .map_sg = nv44_vm_map_sg,
224 .unmap = nv44_vm_unmap,
225 .flush = nv44_vm_flush,
226}; 62};
227 63
228int 64int
@@ -232,5 +68,5 @@ nv44_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu)
232 !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) 68 !nvkm_boolopt(device->cfgopt, "NvPCIE", true))
233 return nv04_mmu_new(device, index, pmmu); 69 return nv04_mmu_new(device, index, pmmu);
234 70
235 return nv04_mmu_new_(&nv44_mmu, device, index, pmmu); 71 return nvkm_mmu_new_(&nv44_mmu, device, index, pmmu);
236} 72}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
index a1f8d65f0276..db3dfbbb2aa0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
@@ -21,207 +21,52 @@
21 * 21 *
22 * Authors: Ben Skeggs 22 * Authors: Ben Skeggs
23 */ 23 */
24#include "priv.h" 24#include "mem.h"
25#include "vmm.h"
25 26
26#include <core/gpuobj.h> 27#include <nvif/class.h>
27#include <subdev/fb.h>
28#include <subdev/timer.h>
29#include <engine/gr.h>
30 28
31static void 29const u8 *
32nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2]) 30nv50_mmu_kind(struct nvkm_mmu *base, int *count)
33{ 31{
34 u64 phys = 0xdeadcafe00000000ULL; 32 /* 0x01: no bank swizzle
35 u32 coverage = 0; 33 * 0x02: bank swizzled
36 34 * 0x7f: invalid
37 if (pgt[0]) { 35 *
38 /* present, 4KiB pages */ 36 * 0x01/0x02 are values understood by the VRAM allocator,
39 phys = 0x00000003 | nvkm_memory_addr(pgt[0]); 37 * and are required to avoid mixing the two types within
40 coverage = (nvkm_memory_size(pgt[0]) >> 3) << 12; 38 * a certain range.
41 } else 39 */
42 if (pgt[1]) { 40 static const u8
43 /* present, 64KiB pages */ 41 kind[128] = {
44 phys = 0x00000001 | nvkm_memory_addr(pgt[1]); 42 0x01, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x00 */
45 coverage = (nvkm_memory_size(pgt[1]) >> 3) << 16; 43 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
46 } 44 0x01, 0x01, 0x01, 0x01, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x10 */
47 45 0x02, 0x02, 0x02, 0x02, 0x7f, 0x7f, 0x7f, 0x7f,
48 if (phys & 1) { 46 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, /* 0x20 */
49 if (coverage <= 32 * 1024 * 1024) 47 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7f,
50 phys |= 0x60; 48 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x30 */
51 else if (coverage <= 64 * 1024 * 1024) 49 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
52 phys |= 0x40; 50 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, /* 0x40 */
53 else if (coverage <= 128 * 1024 * 1024) 51 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7f, 0x7f,
54 phys |= 0x20; 52 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x01, 0x01, 0x7f, /* 0x50 */
55 } 53 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
56 54 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, /* 0x60 */
57 nvkm_kmap(pgd); 55 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
58 nvkm_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); 56 0x01, 0x7f, 0x02, 0x7f, 0x01, 0x7f, 0x02, 0x7f, /* 0x70 */
59 nvkm_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); 57 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x7f, 0x7f
60 nvkm_done(pgd); 58 };
61} 59 *count = ARRAY_SIZE(kind);
62 60 return kind;
63static inline u64
64vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target)
65{
66 phys |= 1; /* present */
67 phys |= (u64)memtype << 40;
68 phys |= target << 4;
69 if (vma->access & NV_MEM_ACCESS_SYS)
70 phys |= (1 << 6);
71 if (!(vma->access & NV_MEM_ACCESS_WO))
72 phys |= (1 << 3);
73 return phys;
74}
75
76static void
77nv50_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt,
78 struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
79{
80 struct nvkm_ram *ram = vma->vm->mmu->subdev.device->fb->ram;
81 u32 comp = (mem->memtype & 0x180) >> 7;
82 u32 block, target;
83 int i;
84
85 /* IGPs don't have real VRAM, re-target to stolen system memory */
86 target = 0;
87 if (ram->stolen) {
88 phys += ram->stolen;
89 target = 3;
90 }
91
92 phys = vm_addr(vma, phys, mem->memtype, target);
93 pte <<= 3;
94 cnt <<= 3;
95
96 nvkm_kmap(pgt);
97 while (cnt) {
98 u32 offset_h = upper_32_bits(phys);
99 u32 offset_l = lower_32_bits(phys);
100
101 for (i = 7; i >= 0; i--) {
102 block = 1 << (i + 3);
103 if (cnt >= block && !(pte & (block - 1)))
104 break;
105 }
106 offset_l |= (i << 7);
107
108 phys += block << (vma->node->type - 3);
109 cnt -= block;
110 if (comp) {
111 u32 tag = mem->tag->offset + ((delta >> 16) * comp);
112 offset_h |= (tag << 17);
113 delta += block << (vma->node->type - 3);
114 }
115
116 while (block) {
117 nvkm_wo32(pgt, pte + 0, offset_l);
118 nvkm_wo32(pgt, pte + 4, offset_h);
119 pte += 8;
120 block -= 8;
121 }
122 }
123 nvkm_done(pgt);
124}
125
126static void
127nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt,
128 struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
129{
130 u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2;
131 pte <<= 3;
132 nvkm_kmap(pgt);
133 while (cnt--) {
134 u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target);
135 nvkm_wo32(pgt, pte + 0, lower_32_bits(phys));
136 nvkm_wo32(pgt, pte + 4, upper_32_bits(phys));
137 pte += 8;
138 }
139 nvkm_done(pgt);
140}
141
142static void
143nv50_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt)
144{
145 pte <<= 3;
146 nvkm_kmap(pgt);
147 while (cnt--) {
148 nvkm_wo32(pgt, pte + 0, 0x00000000);
149 nvkm_wo32(pgt, pte + 4, 0x00000000);
150 pte += 8;
151 }
152 nvkm_done(pgt);
153}
154
155static void
156nv50_vm_flush(struct nvkm_vm *vm)
157{
158 struct nvkm_mmu *mmu = vm->mmu;
159 struct nvkm_subdev *subdev = &mmu->subdev;
160 struct nvkm_device *device = subdev->device;
161 int i, vme;
162
163 mutex_lock(&subdev->mutex);
164 for (i = 0; i < NVKM_SUBDEV_NR; i++) {
165 if (!atomic_read(&vm->engref[i]))
166 continue;
167
168 /* unfortunate hw bug workaround... */
169 if (i == NVKM_ENGINE_GR && device->gr) {
170 int ret = nvkm_gr_tlb_flush(device->gr);
171 if (ret != -ENODEV)
172 continue;
173 }
174
175 switch (i) {
176 case NVKM_ENGINE_GR : vme = 0x00; break;
177 case NVKM_ENGINE_VP :
178 case NVKM_ENGINE_MSPDEC: vme = 0x01; break;
179 case NVKM_SUBDEV_BAR : vme = 0x06; break;
180 case NVKM_ENGINE_MSPPP :
181 case NVKM_ENGINE_MPEG : vme = 0x08; break;
182 case NVKM_ENGINE_BSP :
183 case NVKM_ENGINE_MSVLD : vme = 0x09; break;
184 case NVKM_ENGINE_CIPHER:
185 case NVKM_ENGINE_SEC : vme = 0x0a; break;
186 case NVKM_ENGINE_CE0 : vme = 0x0d; break;
187 default:
188 continue;
189 }
190
191 nvkm_wr32(device, 0x100c80, (vme << 16) | 1);
192 if (nvkm_msec(device, 2000,
193 if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
194 break;
195 ) < 0)
196 nvkm_error(subdev, "vm flush timeout: engine %d\n", vme);
197 }
198 mutex_unlock(&subdev->mutex);
199}
200
201static int
202nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset,
203 struct lock_class_key *key, struct nvkm_vm **pvm)
204{
205 u32 block = (1 << (mmu->func->pgt_bits + 12));
206 if (block > length)
207 block = length;
208
209 return nvkm_vm_create(mmu, offset, length, mm_offset, block, key, pvm);
210} 61}
211 62
212static const struct nvkm_mmu_func 63static const struct nvkm_mmu_func
213nv50_mmu = { 64nv50_mmu = {
214 .limit = (1ULL << 40),
215 .dma_bits = 40, 65 .dma_bits = 40,
216 .pgt_bits = 29 - 12, 66 .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV50}},
217 .spg_shift = 12, 67 .mem = {{ -1, 0, NVIF_CLASS_MEM_NV50}, nv50_mem_new, nv50_mem_map },
218 .lpg_shift = 16, 68 .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV50}, nv50_vmm_new, false, 0x1400 },
219 .create = nv50_vm_create, 69 .kind = nv50_mmu_kind,
220 .map_pgt = nv50_vm_map_pgt,
221 .map = nv50_vm_map,
222 .map_sg = nv50_vm_map_sg,
223 .unmap = nv50_vm_unmap,
224 .flush = nv50_vm_flush,
225}; 70};
226 71
227int 72int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
index 27cedc60b507..d024d8055fcb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
@@ -9,31 +9,57 @@ int nvkm_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *,
9 int index, struct nvkm_mmu **); 9 int index, struct nvkm_mmu **);
10 10
11struct nvkm_mmu_func { 11struct nvkm_mmu_func {
12 void *(*dtor)(struct nvkm_mmu *);
13 int (*oneinit)(struct nvkm_mmu *);
14 void (*init)(struct nvkm_mmu *); 12 void (*init)(struct nvkm_mmu *);
15 13
16 u64 limit;
17 u8 dma_bits; 14 u8 dma_bits;
18 u32 pgt_bits; 15
19 u8 spg_shift; 16 struct {
20 u8 lpg_shift; 17 struct nvkm_sclass user;
21 18 } mmu;
22 int (*create)(struct nvkm_mmu *, u64 offset, u64 length, u64 mm_offset, 19
23 struct lock_class_key *, struct nvkm_vm **); 20 struct {
24 21 struct nvkm_sclass user;
25 void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde, 22 int (*vram)(struct nvkm_mmu *, int type, u8 page, u64 size,
26 struct nvkm_memory *pgt[2]); 23 void *argv, u32 argc, struct nvkm_memory **);
27 void (*map)(struct nvkm_vma *, struct nvkm_memory *, 24 int (*umap)(struct nvkm_mmu *, struct nvkm_memory *, void *argv,
28 struct nvkm_mem *, u32 pte, u32 cnt, 25 u32 argc, u64 *addr, u64 *size, struct nvkm_vma **);
29 u64 phys, u64 delta); 26 } mem;
30 void (*map_sg)(struct nvkm_vma *, struct nvkm_memory *, 27
31 struct nvkm_mem *, u32 pte, u32 cnt, dma_addr_t *); 28 struct {
32 void (*unmap)(struct nvkm_vma *, struct nvkm_memory *pgt, 29 struct nvkm_sclass user;
33 u32 pte, u32 cnt); 30 int (*ctor)(struct nvkm_mmu *, u64 addr, u64 size,
34 void (*flush)(struct nvkm_vm *); 31 void *argv, u32 argc, struct lock_class_key *,
32 const char *name, struct nvkm_vmm **);
33 bool global;
34 u32 pd_offset;
35 } vmm;
36
37 const u8 *(*kind)(struct nvkm_mmu *, int *count);
38 bool kind_sys;
39};
40
41extern const struct nvkm_mmu_func nv04_mmu;
42
43const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count);
44
45const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count);
46
47const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *);
48
49struct nvkm_mmu_pt {
50 union {
51 struct nvkm_mmu_ptc *ptc;
52 struct nvkm_mmu_ptp *ptp;
53 };
54 struct nvkm_memory *memory;
55 bool sub;
56 u16 base;
57 u64 addr;
58 struct list_head head;
35}; 59};
36 60
37int nvkm_vm_create(struct nvkm_mmu *, u64, u64, u64, u32, 61void nvkm_mmu_ptc_dump(struct nvkm_mmu *);
38 struct lock_class_key *, struct nvkm_vm **); 62struct nvkm_mmu_pt *
63nvkm_mmu_ptc_get(struct nvkm_mmu *, u32 size, u32 align, bool zero);
64void nvkm_mmu_ptc_put(struct nvkm_mmu *, bool force, struct nvkm_mmu_pt **);
39#endif 65#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c
new file mode 100644
index 000000000000..fac2f9a45ea6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "umem.h"
23#include "ummu.h"
24
25#include <core/client.h>
26#include <core/memory.h>
27#include <subdev/bar.h>
28
29#include <nvif/class.h>
30#include <nvif/if000a.h>
31#include <nvif/unpack.h>
32
33static const struct nvkm_object_func nvkm_umem;
34struct nvkm_memory *
35nvkm_umem_search(struct nvkm_client *client, u64 handle)
36{
37 struct nvkm_client *master = client->object.client;
38 struct nvkm_memory *memory = NULL;
39 struct nvkm_object *object;
40 struct nvkm_umem *umem;
41
42 object = nvkm_object_search(client, handle, &nvkm_umem);
43 if (IS_ERR(object)) {
44 if (client->super && client != master) {
45 spin_lock(&master->lock);
46 list_for_each_entry(umem, &master->umem, head) {
47 if (umem->object.object == handle) {
48 memory = nvkm_memory_ref(umem->memory);
49 break;
50 }
51 }
52 spin_unlock(&master->lock);
53 }
54 } else {
55 umem = nvkm_umem(object);
56 if (!umem->priv || client->super)
57 memory = nvkm_memory_ref(umem->memory);
58 }
59
60 return memory ? memory : ERR_PTR(-ENOENT);
61}
62
63static int
64nvkm_umem_unmap(struct nvkm_object *object)
65{
66 struct nvkm_umem *umem = nvkm_umem(object);
67
68 if (!umem->map)
69 return -EEXIST;
70
71 if (umem->io) {
72 if (!IS_ERR(umem->bar)) {
73 struct nvkm_device *device = umem->mmu->subdev.device;
74 nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &umem->bar);
75 } else {
76 umem->bar = NULL;
77 }
78 } else {
79 vunmap(umem->map);
80 umem->map = NULL;
81 }
82
83 return 0;
84}
85
86static int
87nvkm_umem_map(struct nvkm_object *object, void *argv, u32 argc,
88 enum nvkm_object_map *type, u64 *handle, u64 *length)
89{
90 struct nvkm_umem *umem = nvkm_umem(object);
91 struct nvkm_mmu *mmu = umem->mmu;
92
93 if (!umem->mappable)
94 return -EINVAL;
95 if (umem->map)
96 return -EEXIST;
97
98 if ((umem->type & NVKM_MEM_HOST) && !argc) {
99 int ret = nvkm_mem_map_host(umem->memory, &umem->map);
100 if (ret)
101 return ret;
102
103 *handle = (unsigned long)(void *)umem->map;
104 *length = nvkm_memory_size(umem->memory);
105 *type = NVKM_OBJECT_MAP_VA;
106 return 0;
107 } else
108 if ((umem->type & NVKM_MEM_VRAM) ||
109 (umem->type & NVKM_MEM_KIND)) {
110 int ret = mmu->func->mem.umap(mmu, umem->memory, argv, argc,
111 handle, length, &umem->bar);
112 if (ret)
113 return ret;
114
115 *type = NVKM_OBJECT_MAP_IO;
116 } else {
117 return -EINVAL;
118 }
119
120 umem->io = (*type == NVKM_OBJECT_MAP_IO);
121 return 0;
122}
123
124static void *
125nvkm_umem_dtor(struct nvkm_object *object)
126{
127 struct nvkm_umem *umem = nvkm_umem(object);
128 spin_lock(&umem->object.client->lock);
129 list_del_init(&umem->head);
130 spin_unlock(&umem->object.client->lock);
131 nvkm_memory_unref(&umem->memory);
132 return umem;
133}
134
135static const struct nvkm_object_func
136nvkm_umem = {
137 .dtor = nvkm_umem_dtor,
138 .map = nvkm_umem_map,
139 .unmap = nvkm_umem_unmap,
140};
141
142int
143nvkm_umem_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
144 struct nvkm_object **pobject)
145{
146 struct nvkm_mmu *mmu = nvkm_ummu(oclass->parent)->mmu;
147 union {
148 struct nvif_mem_v0 v0;
149 } *args = argv;
150 struct nvkm_umem *umem;
151 int type, ret = -ENOSYS;
152 u8 page;
153 u64 size;
154
155 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) {
156 type = args->v0.type;
157 page = args->v0.page;
158 size = args->v0.size;
159 } else
160 return ret;
161
162 if (type >= mmu->type_nr)
163 return -EINVAL;
164
165 if (!(umem = kzalloc(sizeof(*umem), GFP_KERNEL)))
166 return -ENOMEM;
167 nvkm_object_ctor(&nvkm_umem, oclass, &umem->object);
168 umem->mmu = mmu;
169 umem->type = mmu->type[type].type;
170 umem->priv = oclass->client->super;
171 INIT_LIST_HEAD(&umem->head);
172 *pobject = &umem->object;
173
174 if (mmu->type[type].type & NVKM_MEM_MAPPABLE) {
175 page = max_t(u8, page, PAGE_SHIFT);
176 umem->mappable = true;
177 }
178
179 ret = nvkm_mem_new_type(mmu, type, page, size, argv, argc,
180 &umem->memory);
181 if (ret)
182 return ret;
183
184 spin_lock(&umem->object.client->lock);
185 list_add(&umem->head, &umem->object.client->umem);
186 spin_unlock(&umem->object.client->lock);
187
188 args->v0.page = nvkm_memory_page(umem->memory);
189 args->v0.addr = nvkm_memory_addr(umem->memory);
190 args->v0.size = nvkm_memory_size(umem->memory);
191 return 0;
192}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h
new file mode 100644
index 000000000000..85cf692d620a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h
@@ -0,0 +1,26 @@
1#ifndef __NVKM_UMEM_H__
2#define __NVKM_UMEM_H__
3#define nvkm_umem(p) container_of((p), struct nvkm_umem, object)
4#include <core/object.h>
5#include "mem.h"
6
7struct nvkm_umem {
8 struct nvkm_object object;
9 struct nvkm_mmu *mmu;
10 u8 type:8;
11 bool priv:1;
12 bool mappable:1;
13 bool io:1;
14
15 struct nvkm_memory *memory;
16 struct list_head head;
17
18 union {
19 struct nvkm_vma *bar;
20 void *map;
21 };
22};
23
24int nvkm_umem_new(const struct nvkm_oclass *, void *argv, u32 argc,
25 struct nvkm_object **);
26#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c
new file mode 100644
index 000000000000..353f10f92b77
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c
@@ -0,0 +1,178 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "ummu.h"
23#include "umem.h"
24#include "uvmm.h"
25
26#include <core/client.h>
27
28#include <nvif/if0008.h>
29#include <nvif/unpack.h>
30
31static int
32nvkm_ummu_sclass(struct nvkm_object *object, int index,
33 struct nvkm_oclass *oclass)
34{
35 struct nvkm_mmu *mmu = nvkm_ummu(object)->mmu;
36
37 if (mmu->func->mem.user.oclass && oclass->client->super) {
38 if (index-- == 0) {
39 oclass->base = mmu->func->mem.user;
40 oclass->ctor = nvkm_umem_new;
41 return 0;
42 }
43 }
44
45 if (mmu->func->vmm.user.oclass) {
46 if (index-- == 0) {
47 oclass->base = mmu->func->vmm.user;
48 oclass->ctor = nvkm_uvmm_new;
49 return 0;
50 }
51 }
52
53 return -EINVAL;
54}
55
56static int
57nvkm_ummu_heap(struct nvkm_ummu *ummu, void *argv, u32 argc)
58{
59 struct nvkm_mmu *mmu = ummu->mmu;
60 union {
61 struct nvif_mmu_heap_v0 v0;
62 } *args = argv;
63 int ret = -ENOSYS;
64 u8 index;
65
66 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
67 if ((index = args->v0.index) >= mmu->heap_nr)
68 return -EINVAL;
69 args->v0.size = mmu->heap[index].size;
70 } else
71 return ret;
72
73 return 0;
74}
75
76static int
77nvkm_ummu_type(struct nvkm_ummu *ummu, void *argv, u32 argc)
78{
79 struct nvkm_mmu *mmu = ummu->mmu;
80 union {
81 struct nvif_mmu_type_v0 v0;
82 } *args = argv;
83 int ret = -ENOSYS;
84 u8 type, index;
85
86 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
87 if ((index = args->v0.index) >= mmu->type_nr)
88 return -EINVAL;
89 type = mmu->type[index].type;
90 args->v0.heap = mmu->type[index].heap;
91 args->v0.vram = !!(type & NVKM_MEM_VRAM);
92 args->v0.host = !!(type & NVKM_MEM_HOST);
93 args->v0.comp = !!(type & NVKM_MEM_COMP);
94 args->v0.disp = !!(type & NVKM_MEM_DISP);
95 args->v0.kind = !!(type & NVKM_MEM_KIND);
96 args->v0.mappable = !!(type & NVKM_MEM_MAPPABLE);
97 args->v0.coherent = !!(type & NVKM_MEM_COHERENT);
98 args->v0.uncached = !!(type & NVKM_MEM_UNCACHED);
99 } else
100 return ret;
101
102 return 0;
103}
104
105static int
106nvkm_ummu_kind(struct nvkm_ummu *ummu, void *argv, u32 argc)
107{
108 struct nvkm_mmu *mmu = ummu->mmu;
109 union {
110 struct nvif_mmu_kind_v0 v0;
111 } *args = argv;
112 const u8 *kind = NULL;
113 int ret = -ENOSYS, count = 0;
114
115 if (mmu->func->kind)
116 kind = mmu->func->kind(mmu, &count);
117
118 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) {
119 if (argc != args->v0.count * sizeof(*args->v0.data))
120 return -EINVAL;
121 if (args->v0.count > count)
122 return -EINVAL;
123 memcpy(args->v0.data, kind, args->v0.count);
124 } else
125 return ret;
126
127 return 0;
128}
129
130static int
131nvkm_ummu_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
132{
133 struct nvkm_ummu *ummu = nvkm_ummu(object);
134 switch (mthd) {
135 case NVIF_MMU_V0_HEAP: return nvkm_ummu_heap(ummu, argv, argc);
136 case NVIF_MMU_V0_TYPE: return nvkm_ummu_type(ummu, argv, argc);
137 case NVIF_MMU_V0_KIND: return nvkm_ummu_kind(ummu, argv, argc);
138 default:
139 break;
140 }
141 return -EINVAL;
142}
143
144static const struct nvkm_object_func
145nvkm_ummu = {
146 .mthd = nvkm_ummu_mthd,
147 .sclass = nvkm_ummu_sclass,
148};
149
150int
151nvkm_ummu_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
152 void *argv, u32 argc, struct nvkm_object **pobject)
153{
154 union {
155 struct nvif_mmu_v0 v0;
156 } *args = argv;
157 struct nvkm_mmu *mmu = device->mmu;
158 struct nvkm_ummu *ummu;
159 int ret = -ENOSYS, kinds = 0;
160
161 if (mmu->func->kind)
162 mmu->func->kind(mmu, &kinds);
163
164 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
165 args->v0.dmabits = mmu->dma_bits;
166 args->v0.heap_nr = mmu->heap_nr;
167 args->v0.type_nr = mmu->type_nr;
168 args->v0.kind_nr = kinds;
169 } else
170 return ret;
171
172 if (!(ummu = kzalloc(sizeof(*ummu), GFP_KERNEL)))
173 return -ENOMEM;
174 nvkm_object_ctor(&nvkm_ummu, oclass, &ummu->object);
175 ummu->mmu = mmu;
176 *pobject = &ummu->object;
177 return 0;
178}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h
new file mode 100644
index 000000000000..0cd510dcfc68
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h
@@ -0,0 +1,14 @@
1#ifndef __NVKM_UMMU_H__
2#define __NVKM_UMMU_H__
3#define nvkm_ummu(p) container_of((p), struct nvkm_ummu, object)
4#include <core/object.h>
5#include "priv.h"
6
7struct nvkm_ummu {
8 struct nvkm_object object;
9 struct nvkm_mmu *mmu;
10};
11
12int nvkm_ummu_new(struct nvkm_device *, const struct nvkm_oclass *,
13 void *argv, u32 argc, struct nvkm_object **);
14#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
new file mode 100644
index 000000000000..fa81d0c1ba41
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
@@ -0,0 +1,352 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "uvmm.h"
23#include "umem.h"
24#include "ummu.h"
25
26#include <core/client.h>
27#include <core/memory.h>
28
29#include <nvif/if000c.h>
30#include <nvif/unpack.h>
31
32static const struct nvkm_object_func nvkm_uvmm;
33struct nvkm_vmm *
34nvkm_uvmm_search(struct nvkm_client *client, u64 handle)
35{
36 struct nvkm_object *object;
37
38 object = nvkm_object_search(client, handle, &nvkm_uvmm);
39 if (IS_ERR(object))
40 return (void *)object;
41
42 return nvkm_uvmm(object)->vmm;
43}
44
45static int
46nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
47{
48 struct nvkm_client *client = uvmm->object.client;
49 union {
50 struct nvif_vmm_unmap_v0 v0;
51 } *args = argv;
52 struct nvkm_vmm *vmm = uvmm->vmm;
53 struct nvkm_vma *vma;
54 int ret = -ENOSYS;
55 u64 addr;
56
57 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
58 addr = args->v0.addr;
59 } else
60 return ret;
61
62 mutex_lock(&vmm->mutex);
63 vma = nvkm_vmm_node_search(vmm, addr);
64 if (ret = -ENOENT, !vma || vma->addr != addr) {
65 VMM_DEBUG(vmm, "lookup %016llx: %016llx",
66 addr, vma ? vma->addr : ~0ULL);
67 goto done;
68 }
69
70 if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
71 VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
72 vma->user, !client->super, vma->busy);
73 goto done;
74 }
75
76 if (ret = -EINVAL, !vma->memory) {
77 VMM_DEBUG(vmm, "unmapped");
78 goto done;
79 }
80
81 nvkm_vmm_unmap_locked(vmm, vma);
82 ret = 0;
83done:
84 mutex_unlock(&vmm->mutex);
85 return ret;
86}
87
88static int
89nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
90{
91 struct nvkm_client *client = uvmm->object.client;
92 union {
93 struct nvif_vmm_map_v0 v0;
94 } *args = argv;
95 u64 addr, size, handle, offset;
96 struct nvkm_vmm *vmm = uvmm->vmm;
97 struct nvkm_vma *vma;
98 struct nvkm_memory *memory;
99 int ret = -ENOSYS;
100
101 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) {
102 addr = args->v0.addr;
103 size = args->v0.size;
104 handle = args->v0.memory;
105 offset = args->v0.offset;
106 } else
107 return ret;
108
109 if (IS_ERR((memory = nvkm_umem_search(client, handle)))) {
110 VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory));
111 return PTR_ERR(memory);
112 }
113
114 mutex_lock(&vmm->mutex);
115 if (ret = -ENOENT, !(vma = nvkm_vmm_node_search(vmm, addr))) {
116 VMM_DEBUG(vmm, "lookup %016llx", addr);
117 goto fail;
118 }
119
120 if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
121 VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
122 vma->user, !client->super, vma->busy);
123 goto fail;
124 }
125
126 if (ret = -EINVAL, vma->addr != addr || vma->size != size) {
127 if (addr + size > vma->addr + vma->size || vma->memory ||
128 (vma->refd == NVKM_VMA_PAGE_NONE && !vma->mapref)) {
129 VMM_DEBUG(vmm, "split %d %d %d "
130 "%016llx %016llx %016llx %016llx",
131 !!vma->memory, vma->refd, vma->mapref,
132 addr, size, vma->addr, (u64)vma->size);
133 goto fail;
134 }
135
136 if (vma->addr != addr) {
137 const u64 tail = vma->size + vma->addr - addr;
138 if (ret = -ENOMEM, !(vma = nvkm_vma_tail(vma, tail)))
139 goto fail;
140 vma->part = true;
141 nvkm_vmm_node_insert(vmm, vma);
142 }
143
144 if (vma->size != size) {
145 const u64 tail = vma->size - size;
146 struct nvkm_vma *tmp;
147 if (ret = -ENOMEM, !(tmp = nvkm_vma_tail(vma, tail))) {
148 nvkm_vmm_unmap_region(vmm, vma);
149 goto fail;
150 }
151 tmp->part = true;
152 nvkm_vmm_node_insert(vmm, tmp);
153 }
154 }
155 vma->busy = true;
156 mutex_unlock(&vmm->mutex);
157
158 ret = nvkm_memory_map(memory, offset, vmm, vma, argv, argc);
159 if (ret == 0) {
160 /* Successful map will clear vma->busy. */
161 nvkm_memory_unref(&memory);
162 return 0;
163 }
164
165 mutex_lock(&vmm->mutex);
166 vma->busy = false;
167 nvkm_vmm_unmap_region(vmm, vma);
168fail:
169 mutex_unlock(&vmm->mutex);
170 nvkm_memory_unref(&memory);
171 return ret;
172}
173
174static int
175nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
176{
177 struct nvkm_client *client = uvmm->object.client;
178 union {
179 struct nvif_vmm_put_v0 v0;
180 } *args = argv;
181 struct nvkm_vmm *vmm = uvmm->vmm;
182 struct nvkm_vma *vma;
183 int ret = -ENOSYS;
184 u64 addr;
185
186 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
187 addr = args->v0.addr;
188 } else
189 return ret;
190
191 mutex_lock(&vmm->mutex);
192 vma = nvkm_vmm_node_search(vmm, args->v0.addr);
193 if (ret = -ENOENT, !vma || vma->addr != addr || vma->part) {
194 VMM_DEBUG(vmm, "lookup %016llx: %016llx %d", addr,
195 vma ? vma->addr : ~0ULL, vma ? vma->part : 0);
196 goto done;
197 }
198
199 if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
200 VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
201 vma->user, !client->super, vma->busy);
202 goto done;
203 }
204
205 nvkm_vmm_put_locked(vmm, vma);
206 ret = 0;
207done:
208 mutex_unlock(&vmm->mutex);
209 return ret;
210}
211
212static int
213nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
214{
215 struct nvkm_client *client = uvmm->object.client;
216 union {
217 struct nvif_vmm_get_v0 v0;
218 } *args = argv;
219 struct nvkm_vmm *vmm = uvmm->vmm;
220 struct nvkm_vma *vma;
221 int ret = -ENOSYS;
222 bool getref, mapref, sparse;
223 u8 page, align;
224 u64 size;
225
226 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
227 getref = args->v0.type == NVIF_VMM_GET_V0_PTES;
228 mapref = args->v0.type == NVIF_VMM_GET_V0_ADDR;
229 sparse = args->v0.sparse;
230 page = args->v0.page;
231 align = args->v0.align;
232 size = args->v0.size;
233 } else
234 return ret;
235
236 mutex_lock(&vmm->mutex);
237 ret = nvkm_vmm_get_locked(vmm, getref, mapref, sparse,
238 page, align, size, &vma);
239 mutex_unlock(&vmm->mutex);
240 if (ret)
241 return ret;
242
243 args->v0.addr = vma->addr;
244 vma->user = !client->super;
245 return ret;
246}
247
248static int
249nvkm_uvmm_mthd_page(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
250{
251 union {
252 struct nvif_vmm_page_v0 v0;
253 } *args = argv;
254 const struct nvkm_vmm_page *page;
255 int ret = -ENOSYS;
256 u8 type, index, nr;
257
258 page = uvmm->vmm->func->page;
259 for (nr = 0; page[nr].shift; nr++);
260
261 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
262 if ((index = args->v0.index) >= nr)
263 return -EINVAL;
264 type = page[index].type;
265 args->v0.shift = page[index].shift;
266 args->v0.sparse = !!(type & NVKM_VMM_PAGE_SPARSE);
267 args->v0.vram = !!(type & NVKM_VMM_PAGE_VRAM);
268 args->v0.host = !!(type & NVKM_VMM_PAGE_HOST);
269 args->v0.comp = !!(type & NVKM_VMM_PAGE_COMP);
270 } else
271 return -ENOSYS;
272
273 return 0;
274}
275
276static int
277nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
278{
279 struct nvkm_uvmm *uvmm = nvkm_uvmm(object);
280 switch (mthd) {
281 case NVIF_VMM_V0_PAGE : return nvkm_uvmm_mthd_page (uvmm, argv, argc);
282 case NVIF_VMM_V0_GET : return nvkm_uvmm_mthd_get (uvmm, argv, argc);
283 case NVIF_VMM_V0_PUT : return nvkm_uvmm_mthd_put (uvmm, argv, argc);
284 case NVIF_VMM_V0_MAP : return nvkm_uvmm_mthd_map (uvmm, argv, argc);
285 case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc);
286 default:
287 break;
288 }
289 return -EINVAL;
290}
291
292static void *
293nvkm_uvmm_dtor(struct nvkm_object *object)
294{
295 struct nvkm_uvmm *uvmm = nvkm_uvmm(object);
296 nvkm_vmm_unref(&uvmm->vmm);
297 return uvmm;
298}
299
300static const struct nvkm_object_func
301nvkm_uvmm = {
302 .dtor = nvkm_uvmm_dtor,
303 .mthd = nvkm_uvmm_mthd,
304};
305
306int
307nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
308 struct nvkm_object **pobject)
309{
310 struct nvkm_mmu *mmu = nvkm_ummu(oclass->parent)->mmu;
311 const bool more = oclass->base.maxver >= 0;
312 union {
313 struct nvif_vmm_v0 v0;
314 } *args = argv;
315 const struct nvkm_vmm_page *page;
316 struct nvkm_uvmm *uvmm;
317 int ret = -ENOSYS;
318 u64 addr, size;
319
320 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) {
321 addr = args->v0.addr;
322 size = args->v0.size;
323 } else
324 return ret;
325
326 if (!(uvmm = kzalloc(sizeof(*uvmm), GFP_KERNEL)))
327 return -ENOMEM;
328 nvkm_object_ctor(&nvkm_uvmm, oclass, &uvmm->object);
329 *pobject = &uvmm->object;
330
331 if (!mmu->vmm) {
332 ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc,
333 NULL, "user", &uvmm->vmm);
334 if (ret)
335 return ret;
336
337 uvmm->vmm->debug = max(uvmm->vmm->debug, oclass->client->debug);
338 } else {
339 if (size)
340 return -EINVAL;
341
342 uvmm->vmm = nvkm_vmm_ref(mmu->vmm);
343 }
344
345 page = uvmm->vmm->func->page;
346 args->v0.page_nr = 0;
347 while (page && (page++)->shift)
348 args->v0.page_nr++;
349 args->v0.addr = uvmm->vmm->start;
350 args->v0.size = uvmm->vmm->limit;
351 return 0;
352}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h
new file mode 100644
index 000000000000..71dab55e18a9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h
@@ -0,0 +1,14 @@
1#ifndef __NVKM_UVMM_H__
2#define __NVKM_UVMM_H__
3#define nvkm_uvmm(p) container_of((p), struct nvkm_uvmm, object)
4#include <core/object.h>
5#include "vmm.h"
6
7struct nvkm_uvmm {
8 struct nvkm_object object;
9 struct nvkm_vmm *vmm;
10};
11
12int nvkm_uvmm_new(const struct nvkm_oclass *, void *argv, u32 argc,
13 struct nvkm_object **);
14#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
new file mode 100644
index 000000000000..6446bc61b084
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
@@ -0,0 +1,1513 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#define NVKM_VMM_LEVELS_MAX 5
23#include "vmm.h"
24
25#include <subdev/fb.h>
26
27static void
28nvkm_vmm_pt_del(struct nvkm_vmm_pt **ppgt)
29{
30 struct nvkm_vmm_pt *pgt = *ppgt;
31 if (pgt) {
32 kvfree(pgt->pde);
33 kfree(pgt);
34 *ppgt = NULL;
35 }
36}
37
38
39static struct nvkm_vmm_pt *
40nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse,
41 const struct nvkm_vmm_page *page)
42{
43 const u32 pten = 1 << desc->bits;
44 struct nvkm_vmm_pt *pgt;
45 u32 lpte = 0;
46
47 if (desc->type > PGT) {
48 if (desc->type == SPT) {
49 const struct nvkm_vmm_desc *pair = page[-1].desc;
50 lpte = pten >> (desc->bits - pair->bits);
51 } else {
52 lpte = pten;
53 }
54 }
55
56 if (!(pgt = kzalloc(sizeof(*pgt) + lpte, GFP_KERNEL)))
57 return NULL;
58 pgt->page = page ? page->shift : 0;
59 pgt->sparse = sparse;
60
61 if (desc->type == PGD) {
62 pgt->pde = kvzalloc(sizeof(*pgt->pde) * pten, GFP_KERNEL);
63 if (!pgt->pde) {
64 kfree(pgt);
65 return NULL;
66 }
67 }
68
69 return pgt;
70}
71
72struct nvkm_vmm_iter {
73 const struct nvkm_vmm_page *page;
74 const struct nvkm_vmm_desc *desc;
75 struct nvkm_vmm *vmm;
76 u64 cnt;
77 u16 max, lvl;
78 u32 pte[NVKM_VMM_LEVELS_MAX];
79 struct nvkm_vmm_pt *pt[NVKM_VMM_LEVELS_MAX];
80 int flush;
81};
82
83#ifdef CONFIG_NOUVEAU_DEBUG_MMU
84static const char *
85nvkm_vmm_desc_type(const struct nvkm_vmm_desc *desc)
86{
87 switch (desc->type) {
88 case PGD: return "PGD";
89 case PGT: return "PGT";
90 case SPT: return "SPT";
91 case LPT: return "LPT";
92 default:
93 return "UNKNOWN";
94 }
95}
96
97static void
98nvkm_vmm_trace(struct nvkm_vmm_iter *it, char *buf)
99{
100 int lvl;
101 for (lvl = it->max; lvl >= 0; lvl--) {
102 if (lvl >= it->lvl)
103 buf += sprintf(buf, "%05x:", it->pte[lvl]);
104 else
105 buf += sprintf(buf, "xxxxx:");
106 }
107}
108
109#define TRA(i,f,a...) do { \
110 char _buf[NVKM_VMM_LEVELS_MAX * 7]; \
111 struct nvkm_vmm_iter *_it = (i); \
112 nvkm_vmm_trace(_it, _buf); \
113 VMM_TRACE(_it->vmm, "%s "f, _buf, ##a); \
114} while(0)
115#else
116#define TRA(i,f,a...)
117#endif
118
119static inline void
120nvkm_vmm_flush_mark(struct nvkm_vmm_iter *it)
121{
122 it->flush = min(it->flush, it->max - it->lvl);
123}
124
125static inline void
126nvkm_vmm_flush(struct nvkm_vmm_iter *it)
127{
128 if (it->flush != NVKM_VMM_LEVELS_MAX) {
129 if (it->vmm->func->flush) {
130 TRA(it, "flush: %d", it->flush);
131 it->vmm->func->flush(it->vmm, it->flush);
132 }
133 it->flush = NVKM_VMM_LEVELS_MAX;
134 }
135}
136
137static void
138nvkm_vmm_unref_pdes(struct nvkm_vmm_iter *it)
139{
140 const struct nvkm_vmm_desc *desc = it->desc;
141 const int type = desc[it->lvl].type == SPT;
142 struct nvkm_vmm_pt *pgd = it->pt[it->lvl + 1];
143 struct nvkm_vmm_pt *pgt = it->pt[it->lvl];
144 struct nvkm_mmu_pt *pt = pgt->pt[type];
145 struct nvkm_vmm *vmm = it->vmm;
146 u32 pdei = it->pte[it->lvl + 1];
147
148 /* Recurse up the tree, unreferencing/destroying unneeded PDs. */
149 it->lvl++;
150 if (--pgd->refs[0]) {
151 const struct nvkm_vmm_desc_func *func = desc[it->lvl].func;
152 /* PD has other valid PDEs, so we need a proper update. */
153 TRA(it, "PDE unmap %s", nvkm_vmm_desc_type(&desc[it->lvl - 1]));
154 pgt->pt[type] = NULL;
155 if (!pgt->refs[!type]) {
156 /* PDE no longer required. */
157 if (pgd->pt[0]) {
158 if (pgt->sparse) {
159 func->sparse(vmm, pgd->pt[0], pdei, 1);
160 pgd->pde[pdei] = NVKM_VMM_PDE_SPARSE;
161 } else {
162 func->unmap(vmm, pgd->pt[0], pdei, 1);
163 pgd->pde[pdei] = NULL;
164 }
165 } else {
166 /* Special handling for Tesla-class GPUs,
167 * where there's no central PD, but each
168 * instance has its own embedded PD.
169 */
170 func->pde(vmm, pgd, pdei);
171 pgd->pde[pdei] = NULL;
172 }
173 } else {
174 /* PDE was pointing at dual-PTs and we're removing
175 * one of them, leaving the other in place.
176 */
177 func->pde(vmm, pgd, pdei);
178 }
179
180 /* GPU may have cached the PTs, flush before freeing. */
181 nvkm_vmm_flush_mark(it);
182 nvkm_vmm_flush(it);
183 } else {
184 /* PD has no valid PDEs left, so we can just destroy it. */
185 nvkm_vmm_unref_pdes(it);
186 }
187
188 /* Destroy PD/PT. */
189 TRA(it, "PDE free %s", nvkm_vmm_desc_type(&desc[it->lvl - 1]));
190 nvkm_mmu_ptc_put(vmm->mmu, vmm->bootstrapped, &pt);
191 if (!pgt->refs[!type])
192 nvkm_vmm_pt_del(&pgt);
193 it->lvl--;
194}
195
196static void
197nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
198 const struct nvkm_vmm_desc *desc, u32 ptei, u32 ptes)
199{
200 const struct nvkm_vmm_desc *pair = it->page[-1].desc;
201 const u32 sptb = desc->bits - pair->bits;
202 const u32 sptn = 1 << sptb;
203 struct nvkm_vmm *vmm = it->vmm;
204 u32 spti = ptei & (sptn - 1), lpti, pteb;
205
206 /* Determine how many SPTEs are being touched under each LPTE,
207 * and drop reference counts.
208 */
209 for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) {
210 const u32 pten = min(sptn - spti, ptes);
211 pgt->pte[lpti] -= pten;
212 ptes -= pten;
213 }
214
215 /* We're done here if there's no corresponding LPT. */
216 if (!pgt->refs[0])
217 return;
218
219 for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) {
220 /* Skip over any LPTEs that still have valid SPTEs. */
221 if (pgt->pte[pteb] & NVKM_VMM_PTE_SPTES) {
222 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
223 if (!(pgt->pte[ptei] & NVKM_VMM_PTE_SPTES))
224 break;
225 }
226 continue;
227 }
228
229 /* As there's no more non-UNMAPPED SPTEs left in the range
230 * covered by a number of LPTEs, the LPTEs once again take
231 * control over their address range.
232 *
233 * Determine how many LPTEs need to transition state.
234 */
235 pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID;
236 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
237 if (pgt->pte[ptei] & NVKM_VMM_PTE_SPTES)
238 break;
239 pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID;
240 }
241
242 if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) {
243 TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes);
244 pair->func->sparse(vmm, pgt->pt[0], pteb, ptes);
245 } else
246 if (pair->func->invalid) {
247 /* If the MMU supports it, restore the LPTE to the
248 * INVALID state to tell the MMU there is no point
249 * trying to fetch the corresponding SPTEs.
250 */
251 TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes);
252 pair->func->invalid(vmm, pgt->pt[0], pteb, ptes);
253 }
254 }
255}
256
257static bool
258nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
259{
260 const struct nvkm_vmm_desc *desc = it->desc;
261 const int type = desc->type == SPT;
262 struct nvkm_vmm_pt *pgt = it->pt[0];
263
264 /* Drop PTE references. */
265 pgt->refs[type] -= ptes;
266
267 /* Dual-PTs need special handling, unless PDE becoming invalid. */
268 if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1]))
269 nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes);
270
271 /* PT no longer neeed? Destroy it. */
272 if (!pgt->refs[type]) {
273 it->lvl++;
274 TRA(it, "%s empty", nvkm_vmm_desc_type(desc));
275 it->lvl--;
276 nvkm_vmm_unref_pdes(it);
277 return false; /* PTE writes for unmap() not necessary. */
278 }
279
280 return true;
281}
282
283static void
284nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt,
285 const struct nvkm_vmm_desc *desc, u32 ptei, u32 ptes)
286{
287 const struct nvkm_vmm_desc *pair = it->page[-1].desc;
288 const u32 sptb = desc->bits - pair->bits;
289 const u32 sptn = 1 << sptb;
290 struct nvkm_vmm *vmm = it->vmm;
291 u32 spti = ptei & (sptn - 1), lpti, pteb;
292
293 /* Determine how many SPTEs are being touched under each LPTE,
294 * and increase reference counts.
295 */
296 for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) {
297 const u32 pten = min(sptn - spti, ptes);
298 pgt->pte[lpti] += pten;
299 ptes -= pten;
300 }
301
302 /* We're done here if there's no corresponding LPT. */
303 if (!pgt->refs[0])
304 return;
305
306 for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) {
307 /* Skip over any LPTEs that already have valid SPTEs. */
308 if (pgt->pte[pteb] & NVKM_VMM_PTE_VALID) {
309 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
310 if (!(pgt->pte[ptei] & NVKM_VMM_PTE_VALID))
311 break;
312 }
313 continue;
314 }
315
316 /* As there are now non-UNMAPPED SPTEs in the range covered
317 * by a number of LPTEs, we need to transfer control of the
318 * address range to the SPTEs.
319 *
320 * Determine how many LPTEs need to transition state.
321 */
322 pgt->pte[ptei] |= NVKM_VMM_PTE_VALID;
323 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) {
324 if (pgt->pte[ptei] & NVKM_VMM_PTE_VALID)
325 break;
326 pgt->pte[ptei] |= NVKM_VMM_PTE_VALID;
327 }
328
329 if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) {
330 const u32 spti = pteb * sptn;
331 const u32 sptc = ptes * sptn;
332 /* The entire LPTE is marked as sparse, we need
333 * to make sure that the SPTEs are too.
334 */
335 TRA(it, "SPTE %05x: U -> S %d PTEs", spti, sptc);
336 desc->func->sparse(vmm, pgt->pt[1], spti, sptc);
337 /* Sparse LPTEs prevent SPTEs from being accessed. */
338 TRA(it, "LPTE %05x: S -> U %d PTEs", pteb, ptes);
339 pair->func->unmap(vmm, pgt->pt[0], pteb, ptes);
340 } else
341 if (pair->func->invalid) {
342 /* MMU supports blocking SPTEs by marking an LPTE
343 * as INVALID. We need to reverse that here.
344 */
345 TRA(it, "LPTE %05x: I -> U %d PTEs", pteb, ptes);
346 pair->func->unmap(vmm, pgt->pt[0], pteb, ptes);
347 }
348 }
349}
350
351static bool
352nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
353{
354 const struct nvkm_vmm_desc *desc = it->desc;
355 const int type = desc->type == SPT;
356 struct nvkm_vmm_pt *pgt = it->pt[0];
357
358 /* Take PTE references. */
359 pgt->refs[type] += ptes;
360
361 /* Dual-PTs need special handling. */
362 if (desc->type == SPT)
363 nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes);
364
365 return true;
366}
367
368static void
369nvkm_vmm_sparse_ptes(const struct nvkm_vmm_desc *desc,
370 struct nvkm_vmm_pt *pgt, u32 ptei, u32 ptes)
371{
372 if (desc->type == PGD) {
373 while (ptes--)
374 pgt->pde[ptei++] = NVKM_VMM_PDE_SPARSE;
375 } else
376 if (desc->type == LPT) {
377 memset(&pgt->pte[ptei], NVKM_VMM_PTE_SPARSE, ptes);
378 }
379}
380
381static bool
382nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
383{
384 struct nvkm_vmm_pt *pt = it->pt[0];
385 if (it->desc->type == PGD)
386 memset(&pt->pde[ptei], 0x00, sizeof(pt->pde[0]) * ptes);
387 else
388 if (it->desc->type == LPT)
389 memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes);
390 return nvkm_vmm_unref_ptes(it, ptei, ptes);
391}
392
393static bool
394nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
395{
396 nvkm_vmm_sparse_ptes(it->desc, it->pt[0], ptei, ptes);
397 return nvkm_vmm_ref_ptes(it, ptei, ptes);
398}
399
400static bool
401nvkm_vmm_ref_hwpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei)
402{
403 const struct nvkm_vmm_desc *desc = &it->desc[it->lvl - 1];
404 const int type = desc->type == SPT;
405 struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
406 const bool zero = !pgt->sparse && !desc->func->invalid;
407 struct nvkm_vmm *vmm = it->vmm;
408 struct nvkm_mmu *mmu = vmm->mmu;
409 struct nvkm_mmu_pt *pt;
410 u32 pten = 1 << desc->bits;
411 u32 pteb, ptei, ptes;
412 u32 size = desc->size * pten;
413
414 pgd->refs[0]++;
415
416 pgt->pt[type] = nvkm_mmu_ptc_get(mmu, size, desc->align, zero);
417 if (!pgt->pt[type]) {
418 it->lvl--;
419 nvkm_vmm_unref_pdes(it);
420 return false;
421 }
422
423 if (zero)
424 goto done;
425
426 pt = pgt->pt[type];
427
428 if (desc->type == LPT && pgt->refs[1]) {
429 /* SPT already exists covering the same range as this LPT,
430 * which means we need to be careful that any LPTEs which
431 * overlap valid SPTEs are unmapped as opposed to invalid
432 * or sparse, which would prevent the MMU from looking at
433 * the SPTEs on some GPUs.
434 */
435 for (ptei = pteb = 0; ptei < pten; pteb = ptei) {
436 bool spte = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES;
437 for (ptes = 1, ptei++; ptei < pten; ptes++, ptei++) {
438 bool next = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES;
439 if (spte != next)
440 break;
441 }
442
443 if (!spte) {
444 if (pgt->sparse)
445 desc->func->sparse(vmm, pt, pteb, ptes);
446 else
447 desc->func->invalid(vmm, pt, pteb, ptes);
448 memset(&pgt->pte[pteb], 0x00, ptes);
449 } else {
450 desc->func->unmap(vmm, pt, pteb, ptes);
451 while (ptes--)
452 pgt->pte[pteb++] |= NVKM_VMM_PTE_VALID;
453 }
454 }
455 } else {
456 if (pgt->sparse) {
457 nvkm_vmm_sparse_ptes(desc, pgt, 0, pten);
458 desc->func->sparse(vmm, pt, 0, pten);
459 } else {
460 desc->func->invalid(vmm, pt, 0, pten);
461 }
462 }
463
464done:
465 TRA(it, "PDE write %s", nvkm_vmm_desc_type(desc));
466 it->desc[it->lvl].func->pde(it->vmm, pgd, pdei);
467 nvkm_vmm_flush_mark(it);
468 return true;
469}
470
471static bool
472nvkm_vmm_ref_swpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei)
473{
474 const struct nvkm_vmm_desc *desc = &it->desc[it->lvl - 1];
475 struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
476
477 pgt = nvkm_vmm_pt_new(desc, NVKM_VMM_PDE_SPARSED(pgt), it->page);
478 if (!pgt) {
479 if (!pgd->refs[0])
480 nvkm_vmm_unref_pdes(it);
481 return false;
482 }
483
484 pgd->pde[pdei] = pgt;
485 return true;
486}
487
488static inline u64
489nvkm_vmm_iter(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
490 u64 addr, u64 size, const char *name, bool ref,
491 bool (*REF_PTES)(struct nvkm_vmm_iter *, u32, u32),
492 nvkm_vmm_pte_func MAP_PTES, struct nvkm_vmm_map *map,
493 nvkm_vmm_pxe_func CLR_PTES)
494{
495 const struct nvkm_vmm_desc *desc = page->desc;
496 struct nvkm_vmm_iter it;
497 u64 bits = addr >> page->shift;
498
499 it.page = page;
500 it.desc = desc;
501 it.vmm = vmm;
502 it.cnt = size >> page->shift;
503 it.flush = NVKM_VMM_LEVELS_MAX;
504
505 /* Deconstruct address into PTE indices for each mapping level. */
506 for (it.lvl = 0; desc[it.lvl].bits; it.lvl++) {
507 it.pte[it.lvl] = bits & ((1 << desc[it.lvl].bits) - 1);
508 bits >>= desc[it.lvl].bits;
509 }
510 it.max = --it.lvl;
511 it.pt[it.max] = vmm->pd;
512
513 it.lvl = 0;
514 TRA(&it, "%s: %016llx %016llx %d %lld PTEs", name,
515 addr, size, page->shift, it.cnt);
516 it.lvl = it.max;
517
518 /* Depth-first traversal of page tables. */
519 while (it.cnt) {
520 struct nvkm_vmm_pt *pgt = it.pt[it.lvl];
521 const int type = desc->type == SPT;
522 const u32 pten = 1 << desc->bits;
523 const u32 ptei = it.pte[0];
524 const u32 ptes = min_t(u64, it.cnt, pten - ptei);
525
526 /* Walk down the tree, finding page tables for each level. */
527 for (; it.lvl; it.lvl--) {
528 const u32 pdei = it.pte[it.lvl];
529 struct nvkm_vmm_pt *pgd = pgt;
530
531 /* Software PT. */
532 if (ref && NVKM_VMM_PDE_INVALID(pgd->pde[pdei])) {
533 if (!nvkm_vmm_ref_swpt(&it, pgd, pdei))
534 goto fail;
535 }
536 it.pt[it.lvl - 1] = pgt = pgd->pde[pdei];
537
538 /* Hardware PT.
539 *
540 * This is a separate step from above due to GF100 and
541 * newer having dual page tables at some levels, which
542 * are refcounted independently.
543 */
544 if (ref && !pgt->refs[desc[it.lvl - 1].type == SPT]) {
545 if (!nvkm_vmm_ref_hwpt(&it, pgd, pdei))
546 goto fail;
547 }
548 }
549
550 /* Handle PTE updates. */
551 if (!REF_PTES || REF_PTES(&it, ptei, ptes)) {
552 struct nvkm_mmu_pt *pt = pgt->pt[type];
553 if (MAP_PTES || CLR_PTES) {
554 if (MAP_PTES)
555 MAP_PTES(vmm, pt, ptei, ptes, map);
556 else
557 CLR_PTES(vmm, pt, ptei, ptes);
558 nvkm_vmm_flush_mark(&it);
559 }
560 }
561
562 /* Walk back up the tree to the next position. */
563 it.pte[it.lvl] += ptes;
564 it.cnt -= ptes;
565 if (it.cnt) {
566 while (it.pte[it.lvl] == (1 << desc[it.lvl].bits)) {
567 it.pte[it.lvl++] = 0;
568 it.pte[it.lvl]++;
569 }
570 }
571 };
572
573 nvkm_vmm_flush(&it);
574 return ~0ULL;
575
576fail:
577 /* Reconstruct the failure address so the caller is able to
578 * reverse any partially completed operations.
579 */
580 addr = it.pte[it.max--];
581 do {
582 addr = addr << desc[it.max].bits;
583 addr |= it.pte[it.max];
584 } while (it.max--);
585
586 return addr << page->shift;
587}
588
589static void
590nvkm_vmm_ptes_sparse_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
591 u64 addr, u64 size)
592{
593 nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false,
594 nvkm_vmm_sparse_unref_ptes, NULL, NULL,
595 page->desc->func->invalid ?
596 page->desc->func->invalid : page->desc->func->unmap);
597}
598
599static int
600nvkm_vmm_ptes_sparse_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
601 u64 addr, u64 size)
602{
603 if ((page->type & NVKM_VMM_PAGE_SPARSE)) {
604 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "sparse ref",
605 true, nvkm_vmm_sparse_ref_ptes, NULL,
606 NULL, page->desc->func->sparse);
607 if (fail != ~0ULL) {
608 if ((size = fail - addr))
609 nvkm_vmm_ptes_sparse_put(vmm, page, addr, size);
610 return -ENOMEM;
611 }
612 return 0;
613 }
614 return -EINVAL;
615}
616
617static int
618nvkm_vmm_ptes_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref)
619{
620 const struct nvkm_vmm_page *page = vmm->func->page;
621 int m = 0, i;
622 u64 start = addr;
623 u64 block;
624
625 while (size) {
626 /* Limit maximum page size based on remaining size. */
627 while (size < (1ULL << page[m].shift))
628 m++;
629 i = m;
630
631 /* Find largest page size suitable for alignment. */
632 while (!IS_ALIGNED(addr, 1ULL << page[i].shift))
633 i++;
634
635 /* Determine number of PTEs at this page size. */
636 if (i != m) {
637 /* Limited to alignment boundary of next page size. */
638 u64 next = 1ULL << page[i - 1].shift;
639 u64 part = ALIGN(addr, next) - addr;
640 if (size - part >= next)
641 block = (part >> page[i].shift) << page[i].shift;
642 else
643 block = (size >> page[i].shift) << page[i].shift;
644 } else {
645 block = (size >> page[i].shift) << page[i].shift;;
646 }
647
648 /* Perform operation. */
649 if (ref) {
650 int ret = nvkm_vmm_ptes_sparse_get(vmm, &page[i], addr, block);
651 if (ret) {
652 if ((size = addr - start))
653 nvkm_vmm_ptes_sparse(vmm, start, size, false);
654 return ret;
655 }
656 } else {
657 nvkm_vmm_ptes_sparse_put(vmm, &page[i], addr, block);
658 }
659
660 size -= block;
661 addr += block;
662 }
663
664 return 0;
665}
666
667static void
668nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
669 u64 addr, u64 size, bool sparse)
670{
671 const struct nvkm_vmm_desc_func *func = page->desc->func;
672 nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref",
673 false, nvkm_vmm_unref_ptes, NULL, NULL,
674 sparse ? func->sparse : func->invalid ? func->invalid :
675 func->unmap);
676}
677
678static int
679nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
680 u64 addr, u64 size, struct nvkm_vmm_map *map,
681 nvkm_vmm_pte_func func)
682{
683 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true,
684 nvkm_vmm_ref_ptes, func, map, NULL);
685 if (fail != ~0ULL) {
686 if ((size = fail - addr))
687 nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false);
688 return -ENOMEM;
689 }
690 return 0;
691}
692
693static void
694nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
695 u64 addr, u64 size, bool sparse)
696{
697 const struct nvkm_vmm_desc_func *func = page->desc->func;
698 nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, NULL, NULL, NULL,
699 sparse ? func->sparse : func->invalid ? func->invalid :
700 func->unmap);
701}
702
703static void
704nvkm_vmm_ptes_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
705 u64 addr, u64 size, struct nvkm_vmm_map *map,
706 nvkm_vmm_pte_func func)
707{
708 nvkm_vmm_iter(vmm, page, addr, size, "map", false,
709 NULL, func, map, NULL);
710}
711
712static void
713nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
714 u64 addr, u64 size)
715{
716 nvkm_vmm_iter(vmm, page, addr, size, "unref", false,
717 nvkm_vmm_unref_ptes, NULL, NULL, NULL);
718}
719
720static int
721nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page,
722 u64 addr, u64 size)
723{
724 u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true,
725 nvkm_vmm_ref_ptes, NULL, NULL, NULL);
726 if (fail != ~0ULL) {
727 if (fail != addr)
728 nvkm_vmm_ptes_put(vmm, page, addr, fail - addr);
729 return -ENOMEM;
730 }
731 return 0;
732}
733
734static inline struct nvkm_vma *
735nvkm_vma_new(u64 addr, u64 size)
736{
737 struct nvkm_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
738 if (vma) {
739 vma->addr = addr;
740 vma->size = size;
741 vma->page = NVKM_VMA_PAGE_NONE;
742 vma->refd = NVKM_VMA_PAGE_NONE;
743 }
744 return vma;
745}
746
747struct nvkm_vma *
748nvkm_vma_tail(struct nvkm_vma *vma, u64 tail)
749{
750 struct nvkm_vma *new;
751
752 BUG_ON(vma->size == tail);
753
754 if (!(new = nvkm_vma_new(vma->addr + (vma->size - tail), tail)))
755 return NULL;
756 vma->size -= tail;
757
758 new->mapref = vma->mapref;
759 new->sparse = vma->sparse;
760 new->page = vma->page;
761 new->refd = vma->refd;
762 new->used = vma->used;
763 new->part = vma->part;
764 new->user = vma->user;
765 new->busy = vma->busy;
766 list_add(&new->head, &vma->head);
767 return new;
768}
769
770static void
771nvkm_vmm_free_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
772{
773 struct rb_node **ptr = &vmm->free.rb_node;
774 struct rb_node *parent = NULL;
775
776 while (*ptr) {
777 struct nvkm_vma *this = rb_entry(*ptr, typeof(*this), tree);
778 parent = *ptr;
779 if (vma->size < this->size)
780 ptr = &parent->rb_left;
781 else
782 if (vma->size > this->size)
783 ptr = &parent->rb_right;
784 else
785 if (vma->addr < this->addr)
786 ptr = &parent->rb_left;
787 else
788 if (vma->addr > this->addr)
789 ptr = &parent->rb_right;
790 else
791 BUG();
792 }
793
794 rb_link_node(&vma->tree, parent, ptr);
795 rb_insert_color(&vma->tree, &vmm->free);
796}
797
798void
799nvkm_vmm_node_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
800{
801 struct rb_node **ptr = &vmm->root.rb_node;
802 struct rb_node *parent = NULL;
803
804 while (*ptr) {
805 struct nvkm_vma *this = rb_entry(*ptr, typeof(*this), tree);
806 parent = *ptr;
807 if (vma->addr < this->addr)
808 ptr = &parent->rb_left;
809 else
810 if (vma->addr > this->addr)
811 ptr = &parent->rb_right;
812 else
813 BUG();
814 }
815
816 rb_link_node(&vma->tree, parent, ptr);
817 rb_insert_color(&vma->tree, &vmm->root);
818}
819
820struct nvkm_vma *
821nvkm_vmm_node_search(struct nvkm_vmm *vmm, u64 addr)
822{
823 struct rb_node *node = vmm->root.rb_node;
824 while (node) {
825 struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree);
826 if (addr < vma->addr)
827 node = node->rb_left;
828 else
829 if (addr >= vma->addr + vma->size)
830 node = node->rb_right;
831 else
832 return vma;
833 }
834 return NULL;
835}
836
837static void
838nvkm_vmm_dtor(struct nvkm_vmm *vmm)
839{
840 struct nvkm_vma *vma;
841 struct rb_node *node;
842
843 while ((node = rb_first(&vmm->root))) {
844 struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree);
845 nvkm_vmm_put(vmm, &vma);
846 }
847
848 if (vmm->bootstrapped) {
849 const struct nvkm_vmm_page *page = vmm->func->page;
850 const u64 limit = vmm->limit - vmm->start;
851
852 while (page[1].shift)
853 page++;
854
855 nvkm_mmu_ptc_dump(vmm->mmu);
856 nvkm_vmm_ptes_put(vmm, page, vmm->start, limit);
857 }
858
859 vma = list_first_entry(&vmm->list, typeof(*vma), head);
860 list_del(&vma->head);
861 kfree(vma);
862 WARN_ON(!list_empty(&vmm->list));
863
864 if (vmm->nullp) {
865 dma_free_coherent(vmm->mmu->subdev.device->dev, 16 * 1024,
866 vmm->nullp, vmm->null);
867 }
868
869 if (vmm->pd) {
870 nvkm_mmu_ptc_put(vmm->mmu, true, &vmm->pd->pt[0]);
871 nvkm_vmm_pt_del(&vmm->pd);
872 }
873}
874
875int
876nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
877 u32 pd_header, u64 addr, u64 size, struct lock_class_key *key,
878 const char *name, struct nvkm_vmm *vmm)
879{
880 static struct lock_class_key _key;
881 const struct nvkm_vmm_page *page = func->page;
882 const struct nvkm_vmm_desc *desc;
883 struct nvkm_vma *vma;
884 int levels, bits = 0;
885
886 vmm->func = func;
887 vmm->mmu = mmu;
888 vmm->name = name;
889 vmm->debug = mmu->subdev.debug;
890 kref_init(&vmm->kref);
891
892 __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key);
893
894 /* Locate the smallest page size supported by the backend, it will
895 * have the the deepest nesting of page tables.
896 */
897 while (page[1].shift)
898 page++;
899
900 /* Locate the structure that describes the layout of the top-level
901 * page table, and determine the number of valid bits in a virtual
902 * address.
903 */
904 for (levels = 0, desc = page->desc; desc->bits; desc++, levels++)
905 bits += desc->bits;
906 bits += page->shift;
907 desc--;
908
909 if (WARN_ON(levels > NVKM_VMM_LEVELS_MAX))
910 return -EINVAL;
911
912 vmm->start = addr;
913 vmm->limit = size ? (addr + size) : (1ULL << bits);
914 if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits))
915 return -EINVAL;
916
917 /* Allocate top-level page table. */
918 vmm->pd = nvkm_vmm_pt_new(desc, false, NULL);
919 if (!vmm->pd)
920 return -ENOMEM;
921 vmm->pd->refs[0] = 1;
922 INIT_LIST_HEAD(&vmm->join);
923
924 /* ... and the GPU storage for it, except on Tesla-class GPUs that
925 * have the PD embedded in the instance structure.
926 */
927 if (desc->size) {
928 const u32 size = pd_header + desc->size * (1 << desc->bits);
929 vmm->pd->pt[0] = nvkm_mmu_ptc_get(mmu, size, desc->align, true);
930 if (!vmm->pd->pt[0])
931 return -ENOMEM;
932 }
933
934 /* Initialise address-space MM. */
935 INIT_LIST_HEAD(&vmm->list);
936 vmm->free = RB_ROOT;
937 vmm->root = RB_ROOT;
938
939 if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start)))
940 return -ENOMEM;
941
942 nvkm_vmm_free_insert(vmm, vma);
943 list_add(&vma->head, &vmm->list);
944 return 0;
945}
946
947int
948nvkm_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
949 u32 hdr, u64 addr, u64 size, struct lock_class_key *key,
950 const char *name, struct nvkm_vmm **pvmm)
951{
952 if (!(*pvmm = kzalloc(sizeof(**pvmm), GFP_KERNEL)))
953 return -ENOMEM;
954 return nvkm_vmm_ctor(func, mmu, hdr, addr, size, key, name, *pvmm);
955}
956
957#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL : \
958 list_entry((root)->head.dir, struct nvkm_vma, head)
959
960void
961nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
962{
963 struct nvkm_vma *next;
964
965 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags);
966 nvkm_memory_unref(&vma->memory);
967
968 if (vma->part) {
969 struct nvkm_vma *prev = node(vma, prev);
970 if (!prev->memory) {
971 prev->size += vma->size;
972 rb_erase(&vma->tree, &vmm->root);
973 list_del(&vma->head);
974 kfree(vma);
975 vma = prev;
976 }
977 }
978
979 next = node(vma, next);
980 if (next && next->part) {
981 if (!next->memory) {
982 vma->size += next->size;
983 rb_erase(&next->tree, &vmm->root);
984 list_del(&next->head);
985 kfree(next);
986 }
987 }
988}
989
990void
991nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
992{
993 const struct nvkm_vmm_page *page = &vmm->func->page[vma->refd];
994
995 if (vma->mapref) {
996 nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse);
997 vma->refd = NVKM_VMA_PAGE_NONE;
998 } else {
999 nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse);
1000 }
1001
1002 nvkm_vmm_unmap_region(vmm, vma);
1003}
1004
1005void
1006nvkm_vmm_unmap(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
1007{
1008 if (vma->memory) {
1009 mutex_lock(&vmm->mutex);
1010 nvkm_vmm_unmap_locked(vmm, vma);
1011 mutex_unlock(&vmm->mutex);
1012 }
1013}
1014
1015static int
1016nvkm_vmm_map_valid(struct nvkm_vmm *vmm, struct nvkm_vma *vma,
1017 void *argv, u32 argc, struct nvkm_vmm_map *map)
1018{
1019 switch (nvkm_memory_target(map->memory)) {
1020 case NVKM_MEM_TARGET_VRAM:
1021 if (!(map->page->type & NVKM_VMM_PAGE_VRAM)) {
1022 VMM_DEBUG(vmm, "%d !VRAM", map->page->shift);
1023 return -EINVAL;
1024 }
1025 break;
1026 case NVKM_MEM_TARGET_HOST:
1027 case NVKM_MEM_TARGET_NCOH:
1028 if (!(map->page->type & NVKM_VMM_PAGE_HOST)) {
1029 VMM_DEBUG(vmm, "%d !HOST", map->page->shift);
1030 return -EINVAL;
1031 }
1032 break;
1033 default:
1034 WARN_ON(1);
1035 return -ENOSYS;
1036 }
1037
1038 if (!IS_ALIGNED( vma->addr, 1ULL << map->page->shift) ||
1039 !IS_ALIGNED((u64)vma->size, 1ULL << map->page->shift) ||
1040 !IS_ALIGNED( map->offset, 1ULL << map->page->shift) ||
1041 nvkm_memory_page(map->memory) < map->page->shift) {
1042 VMM_DEBUG(vmm, "alignment %016llx %016llx %016llx %d %d",
1043 vma->addr, (u64)vma->size, map->offset, map->page->shift,
1044 nvkm_memory_page(map->memory));
1045 return -EINVAL;
1046 }
1047
1048 return vmm->func->valid(vmm, argv, argc, map);
1049}
1050
1051static int
1052nvkm_vmm_map_choose(struct nvkm_vmm *vmm, struct nvkm_vma *vma,
1053 void *argv, u32 argc, struct nvkm_vmm_map *map)
1054{
1055 for (map->page = vmm->func->page; map->page->shift; map->page++) {
1056 VMM_DEBUG(vmm, "trying %d", map->page->shift);
1057 if (!nvkm_vmm_map_valid(vmm, vma, argv, argc, map))
1058 return 0;
1059 }
1060 return -EINVAL;
1061}
1062
1063static int
1064nvkm_vmm_map_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma,
1065 void *argv, u32 argc, struct nvkm_vmm_map *map)
1066{
1067 nvkm_vmm_pte_func func;
1068 int ret;
1069
1070 /* Make sure we won't overrun the end of the memory object. */
1071 if (unlikely(nvkm_memory_size(map->memory) < map->offset + vma->size)) {
1072 VMM_DEBUG(vmm, "overrun %016llx %016llx %016llx",
1073 nvkm_memory_size(map->memory),
1074 map->offset, (u64)vma->size);
1075 return -EINVAL;
1076 }
1077
1078 /* Check remaining arguments for validity. */
1079 if (vma->page == NVKM_VMA_PAGE_NONE &&
1080 vma->refd == NVKM_VMA_PAGE_NONE) {
1081 /* Find the largest page size we can perform the mapping at. */
1082 const u32 debug = vmm->debug;
1083 vmm->debug = 0;
1084 ret = nvkm_vmm_map_choose(vmm, vma, argv, argc, map);
1085 vmm->debug = debug;
1086 if (ret) {
1087 VMM_DEBUG(vmm, "invalid at any page size");
1088 nvkm_vmm_map_choose(vmm, vma, argv, argc, map);
1089 return -EINVAL;
1090 }
1091 } else {
1092 /* Page size of the VMA is already pre-determined. */
1093 if (vma->refd != NVKM_VMA_PAGE_NONE)
1094 map->page = &vmm->func->page[vma->refd];
1095 else
1096 map->page = &vmm->func->page[vma->page];
1097
1098 ret = nvkm_vmm_map_valid(vmm, vma, argv, argc, map);
1099 if (ret) {
1100 VMM_DEBUG(vmm, "invalid %d\n", ret);
1101 return ret;
1102 }
1103 }
1104
1105 /* Deal with the 'offset' argument, and fetch the backend function. */
1106 map->off = map->offset;
1107 if (map->mem) {
1108 for (; map->off; map->mem = map->mem->next) {
1109 u64 size = (u64)map->mem->length << NVKM_RAM_MM_SHIFT;
1110 if (size > map->off)
1111 break;
1112 map->off -= size;
1113 }
1114 func = map->page->desc->func->mem;
1115 } else
1116 if (map->sgl) {
1117 for (; map->off; map->sgl = sg_next(map->sgl)) {
1118 u64 size = sg_dma_len(map->sgl);
1119 if (size > map->off)
1120 break;
1121 map->off -= size;
1122 }
1123 func = map->page->desc->func->sgl;
1124 } else {
1125 map->dma += map->offset >> PAGE_SHIFT;
1126 map->off = map->offset & PAGE_MASK;
1127 func = map->page->desc->func->dma;
1128 }
1129
1130 /* Perform the map. */
1131 if (vma->refd == NVKM_VMA_PAGE_NONE) {
1132 ret = nvkm_vmm_ptes_get_map(vmm, map->page, vma->addr, vma->size, map, func);
1133 if (ret)
1134 return ret;
1135
1136 vma->refd = map->page - vmm->func->page;
1137 } else {
1138 nvkm_vmm_ptes_map(vmm, map->page, vma->addr, vma->size, map, func);
1139 }
1140
1141 nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags);
1142 nvkm_memory_unref(&vma->memory);
1143 vma->memory = nvkm_memory_ref(map->memory);
1144 vma->tags = map->tags;
1145 return 0;
1146}
1147
1148int
1149nvkm_vmm_map(struct nvkm_vmm *vmm, struct nvkm_vma *vma, void *argv, u32 argc,
1150 struct nvkm_vmm_map *map)
1151{
1152 int ret;
1153 mutex_lock(&vmm->mutex);
1154 ret = nvkm_vmm_map_locked(vmm, vma, argv, argc, map);
1155 vma->busy = false;
1156 mutex_unlock(&vmm->mutex);
1157 return ret;
1158}
1159
1160static void
1161nvkm_vmm_put_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
1162{
1163 struct nvkm_vma *prev, *next;
1164
1165 if ((prev = node(vma, prev)) && !prev->used) {
1166 rb_erase(&prev->tree, &vmm->free);
1167 list_del(&prev->head);
1168 vma->addr = prev->addr;
1169 vma->size += prev->size;
1170 kfree(prev);
1171 }
1172
1173 if ((next = node(vma, next)) && !next->used) {
1174 rb_erase(&next->tree, &vmm->free);
1175 list_del(&next->head);
1176 vma->size += next->size;
1177 kfree(next);
1178 }
1179
1180 nvkm_vmm_free_insert(vmm, vma);
1181}
1182
1183void
1184nvkm_vmm_put_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
1185{
1186 const struct nvkm_vmm_page *page = vmm->func->page;
1187 struct nvkm_vma *next = vma;
1188
1189 BUG_ON(vma->part);
1190
1191 if (vma->mapref || !vma->sparse) {
1192 do {
1193 const bool map = next->memory != NULL;
1194 const u8 refd = next->refd;
1195 const u64 addr = next->addr;
1196 u64 size = next->size;
1197
1198 /* Merge regions that are in the same state. */
1199 while ((next = node(next, next)) && next->part &&
1200 (next->memory != NULL) == map &&
1201 (next->refd == refd))
1202 size += next->size;
1203
1204 if (map) {
1205 /* Region(s) are mapped, merge the unmap
1206 * and dereference into a single walk of
1207 * the page tree.
1208 */
1209 nvkm_vmm_ptes_unmap_put(vmm, &page[refd], addr,
1210 size, vma->sparse);
1211 } else
1212 if (refd != NVKM_VMA_PAGE_NONE) {
1213 /* Drop allocation-time PTE references. */
1214 nvkm_vmm_ptes_put(vmm, &page[refd], addr, size);
1215 }
1216 } while (next && next->part);
1217 }
1218
1219 /* Merge any mapped regions that were split from the initial
1220 * address-space allocation back into the allocated VMA, and
1221 * release memory/compression resources.
1222 */
1223 next = vma;
1224 do {
1225 if (next->memory)
1226 nvkm_vmm_unmap_region(vmm, next);
1227 } while ((next = node(vma, next)) && next->part);
1228
1229 if (vma->sparse && !vma->mapref) {
1230 /* Sparse region that was allocated with a fixed page size,
1231 * meaning all relevant PTEs were referenced once when the
1232 * region was allocated, and remained that way, regardless
1233 * of whether memory was mapped into it afterwards.
1234 *
1235 * The process of unmapping, unsparsing, and dereferencing
1236 * PTEs can be done in a single page tree walk.
1237 */
1238 nvkm_vmm_ptes_sparse_put(vmm, &page[vma->refd], vma->addr, vma->size);
1239 } else
1240 if (vma->sparse) {
1241 /* Sparse region that wasn't allocated with a fixed page size,
1242 * PTE references were taken both at allocation time (to make
1243 * the GPU see the region as sparse), and when mapping memory
1244 * into the region.
1245 *
1246 * The latter was handled above, and the remaining references
1247 * are dealt with here.
1248 */
1249 nvkm_vmm_ptes_sparse(vmm, vma->addr, vma->size, false);
1250 }
1251
1252 /* Remove VMA from the list of allocated nodes. */
1253 rb_erase(&vma->tree, &vmm->root);
1254
1255 /* Merge VMA back into the free list. */
1256 vma->page = NVKM_VMA_PAGE_NONE;
1257 vma->refd = NVKM_VMA_PAGE_NONE;
1258 vma->used = false;
1259 vma->user = false;
1260 nvkm_vmm_put_region(vmm, vma);
1261}
1262
1263void
1264nvkm_vmm_put(struct nvkm_vmm *vmm, struct nvkm_vma **pvma)
1265{
1266 struct nvkm_vma *vma = *pvma;
1267 if (vma) {
1268 mutex_lock(&vmm->mutex);
1269 nvkm_vmm_put_locked(vmm, vma);
1270 mutex_unlock(&vmm->mutex);
1271 *pvma = NULL;
1272 }
1273}
1274
1275int
1276nvkm_vmm_get_locked(struct nvkm_vmm *vmm, bool getref, bool mapref, bool sparse,
1277 u8 shift, u8 align, u64 size, struct nvkm_vma **pvma)
1278{
1279 const struct nvkm_vmm_page *page = &vmm->func->page[NVKM_VMA_PAGE_NONE];
1280 struct rb_node *node = NULL, *temp;
1281 struct nvkm_vma *vma = NULL, *tmp;
1282 u64 addr, tail;
1283 int ret;
1284
1285 VMM_TRACE(vmm, "getref %d mapref %d sparse %d "
1286 "shift: %d align: %d size: %016llx",
1287 getref, mapref, sparse, shift, align, size);
1288
1289 /* Zero-sized, or lazily-allocated sparse VMAs, make no sense. */
1290 if (unlikely(!size || (!getref && !mapref && sparse))) {
1291 VMM_DEBUG(vmm, "args %016llx %d %d %d",
1292 size, getref, mapref, sparse);
1293 return -EINVAL;
1294 }
1295
1296 /* Tesla-class GPUs can only select page size per-PDE, which means
1297 * we're required to know the mapping granularity up-front to find
1298 * a suitable region of address-space.
1299 *
1300 * The same goes if we're requesting up-front allocation of PTES.
1301 */
1302 if (unlikely((getref || vmm->func->page_block) && !shift)) {
1303 VMM_DEBUG(vmm, "page size required: %d %016llx",
1304 getref, vmm->func->page_block);
1305 return -EINVAL;
1306 }
1307
1308 /* If a specific page size was requested, determine its index and
1309 * make sure the requested size is a multiple of the page size.
1310 */
1311 if (shift) {
1312 for (page = vmm->func->page; page->shift; page++) {
1313 if (shift == page->shift)
1314 break;
1315 }
1316
1317 if (!page->shift || !IS_ALIGNED(size, 1ULL << page->shift)) {
1318 VMM_DEBUG(vmm, "page %d %016llx", shift, size);
1319 return -EINVAL;
1320 }
1321 align = max_t(u8, align, shift);
1322 } else {
1323 align = max_t(u8, align, 12);
1324 }
1325
1326 /* Locate smallest block that can possibly satisfy the allocation. */
1327 temp = vmm->free.rb_node;
1328 while (temp) {
1329 struct nvkm_vma *this = rb_entry(temp, typeof(*this), tree);
1330 if (this->size < size) {
1331 temp = temp->rb_right;
1332 } else {
1333 node = temp;
1334 temp = temp->rb_left;
1335 }
1336 }
1337
1338 if (unlikely(!node))
1339 return -ENOSPC;
1340
1341 /* Take into account alignment restrictions, trying larger blocks
1342 * in turn until we find a suitable free block.
1343 */
1344 do {
1345 struct nvkm_vma *this = rb_entry(node, typeof(*this), tree);
1346 struct nvkm_vma *prev = node(this, prev);
1347 struct nvkm_vma *next = node(this, next);
1348 const int p = page - vmm->func->page;
1349
1350 addr = this->addr;
1351 if (vmm->func->page_block && prev && prev->page != p)
1352 addr = roundup(addr, vmm->func->page_block);
1353 addr = ALIGN(addr, 1ULL << align);
1354
1355 tail = this->addr + this->size;
1356 if (vmm->func->page_block && next && next->page != p)
1357 tail = rounddown(tail, vmm->func->page_block);
1358
1359 if (addr <= tail && tail - addr >= size) {
1360 rb_erase(&this->tree, &vmm->free);
1361 vma = this;
1362 break;
1363 }
1364 } while ((node = rb_next(node)));
1365
1366 if (unlikely(!vma))
1367 return -ENOSPC;
1368
1369 /* If the VMA we found isn't already exactly the requested size,
1370 * it needs to be split, and the remaining free blocks returned.
1371 */
1372 if (addr != vma->addr) {
1373 if (!(tmp = nvkm_vma_tail(vma, vma->size + vma->addr - addr))) {
1374 nvkm_vmm_put_region(vmm, vma);
1375 return -ENOMEM;
1376 }
1377 nvkm_vmm_free_insert(vmm, vma);
1378 vma = tmp;
1379 }
1380
1381 if (size != vma->size) {
1382 if (!(tmp = nvkm_vma_tail(vma, vma->size - size))) {
1383 nvkm_vmm_put_region(vmm, vma);
1384 return -ENOMEM;
1385 }
1386 nvkm_vmm_free_insert(vmm, tmp);
1387 }
1388
1389 /* Pre-allocate page tables and/or setup sparse mappings. */
1390 if (sparse && getref)
1391 ret = nvkm_vmm_ptes_sparse_get(vmm, page, vma->addr, vma->size);
1392 else if (sparse)
1393 ret = nvkm_vmm_ptes_sparse(vmm, vma->addr, vma->size, true);
1394 else if (getref)
1395 ret = nvkm_vmm_ptes_get(vmm, page, vma->addr, vma->size);
1396 else
1397 ret = 0;
1398 if (ret) {
1399 nvkm_vmm_put_region(vmm, vma);
1400 return ret;
1401 }
1402
1403 vma->mapref = mapref && !getref;
1404 vma->sparse = sparse;
1405 vma->page = page - vmm->func->page;
1406 vma->refd = getref ? vma->page : NVKM_VMA_PAGE_NONE;
1407 vma->used = true;
1408 nvkm_vmm_node_insert(vmm, vma);
1409 *pvma = vma;
1410 return 0;
1411}
1412
1413int
1414nvkm_vmm_get(struct nvkm_vmm *vmm, u8 page, u64 size, struct nvkm_vma **pvma)
1415{
1416 int ret;
1417 mutex_lock(&vmm->mutex);
1418 ret = nvkm_vmm_get_locked(vmm, false, true, false, page, 0, size, pvma);
1419 mutex_unlock(&vmm->mutex);
1420 return ret;
1421}
1422
1423void
1424nvkm_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
1425{
1426 if (vmm->func->part && inst) {
1427 mutex_lock(&vmm->mutex);
1428 vmm->func->part(vmm, inst);
1429 mutex_unlock(&vmm->mutex);
1430 }
1431}
1432
1433int
1434nvkm_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
1435{
1436 int ret = 0;
1437 if (vmm->func->join) {
1438 mutex_lock(&vmm->mutex);
1439 ret = vmm->func->join(vmm, inst);
1440 mutex_unlock(&vmm->mutex);
1441 }
1442 return ret;
1443}
1444
1445static bool
1446nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes)
1447{
1448 const struct nvkm_vmm_desc *desc = it->desc;
1449 const int type = desc->type == SPT;
1450 nvkm_memory_boot(it->pt[0]->pt[type]->memory, it->vmm);
1451 return false;
1452}
1453
1454int
1455nvkm_vmm_boot(struct nvkm_vmm *vmm)
1456{
1457 const struct nvkm_vmm_page *page = vmm->func->page;
1458 const u64 limit = vmm->limit - vmm->start;
1459 int ret;
1460
1461 while (page[1].shift)
1462 page++;
1463
1464 ret = nvkm_vmm_ptes_get(vmm, page, vmm->start, limit);
1465 if (ret)
1466 return ret;
1467
1468 nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false,
1469 nvkm_vmm_boot_ptes, NULL, NULL, NULL);
1470 vmm->bootstrapped = true;
1471 return 0;
1472}
1473
1474static void
1475nvkm_vmm_del(struct kref *kref)
1476{
1477 struct nvkm_vmm *vmm = container_of(kref, typeof(*vmm), kref);
1478 nvkm_vmm_dtor(vmm);
1479 kfree(vmm);
1480}
1481
1482void
1483nvkm_vmm_unref(struct nvkm_vmm **pvmm)
1484{
1485 struct nvkm_vmm *vmm = *pvmm;
1486 if (vmm) {
1487 kref_put(&vmm->kref, nvkm_vmm_del);
1488 *pvmm = NULL;
1489 }
1490}
1491
1492struct nvkm_vmm *
1493nvkm_vmm_ref(struct nvkm_vmm *vmm)
1494{
1495 if (vmm)
1496 kref_get(&vmm->kref);
1497 return vmm;
1498}
1499
1500int
1501nvkm_vmm_new(struct nvkm_device *device, u64 addr, u64 size, void *argv,
1502 u32 argc, struct lock_class_key *key, const char *name,
1503 struct nvkm_vmm **pvmm)
1504{
1505 struct nvkm_mmu *mmu = device->mmu;
1506 struct nvkm_vmm *vmm = NULL;
1507 int ret;
1508 ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, key, name, &vmm);
1509 if (ret)
1510 nvkm_vmm_unref(&vmm);
1511 *pvmm = vmm;
1512 return ret;
1513}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
new file mode 100644
index 000000000000..6d8f61ea467a
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
@@ -0,0 +1,310 @@
1#ifndef __NVKM_VMM_H__
2#define __NVKM_VMM_H__
3#include "priv.h"
4#include <core/memory.h>
5enum nvkm_memory_target;
6
7struct nvkm_vmm_pt {
8 /* Some GPUs have a mapping level with a dual page tables to
9 * support large and small pages in the same address-range.
10 *
11 * We track the state of both page tables in one place, which
12 * is why there's multiple PT pointers/refcounts here.
13 */
14 struct nvkm_mmu_pt *pt[2];
15 u32 refs[2];
16
17 /* Page size handled by this PT.
18 *
19 * Tesla backend needs to know this when writinge PDEs,
20 * otherwise unnecessary.
21 */
22 u8 page;
23
24 /* Entire page table sparse.
25 *
26 * Used to propagate sparseness to child page tables.
27 */
28 bool sparse:1;
29
30 /* Tracking for page directories.
31 *
32 * The array is indexed by PDE, and will either point to the
33 * child page table, or indicate the PDE is marked as sparse.
34 **/
35#define NVKM_VMM_PDE_INVALID(pde) IS_ERR_OR_NULL(pde)
36#define NVKM_VMM_PDE_SPARSED(pde) IS_ERR(pde)
37#define NVKM_VMM_PDE_SPARSE ERR_PTR(-EBUSY)
38 struct nvkm_vmm_pt **pde;
39
40 /* Tracking for dual page tables.
41 *
42 * There's one entry for each LPTE, keeping track of whether
43 * there are valid SPTEs in the same address-range.
44 *
45 * This information is used to manage LPTE state transitions.
46 */
47#define NVKM_VMM_PTE_SPARSE 0x80
48#define NVKM_VMM_PTE_VALID 0x40
49#define NVKM_VMM_PTE_SPTES 0x3f
50 u8 pte[];
51};
52
53typedef void (*nvkm_vmm_pxe_func)(struct nvkm_vmm *,
54 struct nvkm_mmu_pt *, u32 ptei, u32 ptes);
55typedef void (*nvkm_vmm_pde_func)(struct nvkm_vmm *,
56 struct nvkm_vmm_pt *, u32 pdei);
57typedef void (*nvkm_vmm_pte_func)(struct nvkm_vmm *, struct nvkm_mmu_pt *,
58 u32 ptei, u32 ptes, struct nvkm_vmm_map *);
59
60struct nvkm_vmm_desc_func {
61 nvkm_vmm_pxe_func invalid;
62 nvkm_vmm_pxe_func unmap;
63 nvkm_vmm_pxe_func sparse;
64
65 nvkm_vmm_pde_func pde;
66
67 nvkm_vmm_pte_func mem;
68 nvkm_vmm_pte_func dma;
69 nvkm_vmm_pte_func sgl;
70};
71
72extern const struct nvkm_vmm_desc_func gf100_vmm_pgd;
73void gf100_vmm_pgd_pde(struct nvkm_vmm *, struct nvkm_vmm_pt *, u32);
74extern const struct nvkm_vmm_desc_func gf100_vmm_pgt;
75void gf100_vmm_pgt_unmap(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32);
76void gf100_vmm_pgt_mem(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32,
77 struct nvkm_vmm_map *);
78void gf100_vmm_pgt_dma(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32,
79 struct nvkm_vmm_map *);
80void gf100_vmm_pgt_sgl(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32,
81 struct nvkm_vmm_map *);
82
83void gk104_vmm_lpt_invalid(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32);
84
85struct nvkm_vmm_desc {
86 enum {
87 PGD,
88 PGT,
89 SPT,
90 LPT,
91 } type;
92 u8 bits; /* VMA bits covered by PT. */
93 u8 size; /* Bytes-per-PTE. */
94 u32 align; /* PT address alignment. */
95 const struct nvkm_vmm_desc_func *func;
96};
97
98extern const struct nvkm_vmm_desc gk104_vmm_desc_16_12[];
99extern const struct nvkm_vmm_desc gk104_vmm_desc_16_16[];
100extern const struct nvkm_vmm_desc gk104_vmm_desc_17_12[];
101extern const struct nvkm_vmm_desc gk104_vmm_desc_17_17[];
102
103extern const struct nvkm_vmm_desc gm200_vmm_desc_16_12[];
104extern const struct nvkm_vmm_desc gm200_vmm_desc_16_16[];
105extern const struct nvkm_vmm_desc gm200_vmm_desc_17_12[];
106extern const struct nvkm_vmm_desc gm200_vmm_desc_17_17[];
107
108extern const struct nvkm_vmm_desc gp100_vmm_desc_12[];
109extern const struct nvkm_vmm_desc gp100_vmm_desc_16[];
110
111struct nvkm_vmm_page {
112 u8 shift;
113 const struct nvkm_vmm_desc *desc;
114#define NVKM_VMM_PAGE_SPARSE 0x01
115#define NVKM_VMM_PAGE_VRAM 0x02
116#define NVKM_VMM_PAGE_HOST 0x04
117#define NVKM_VMM_PAGE_COMP 0x08
118#define NVKM_VMM_PAGE_Sxxx (NVKM_VMM_PAGE_SPARSE)
119#define NVKM_VMM_PAGE_xVxx (NVKM_VMM_PAGE_VRAM)
120#define NVKM_VMM_PAGE_SVxx (NVKM_VMM_PAGE_Sxxx | NVKM_VMM_PAGE_VRAM)
121#define NVKM_VMM_PAGE_xxHx (NVKM_VMM_PAGE_HOST)
122#define NVKM_VMM_PAGE_SxHx (NVKM_VMM_PAGE_Sxxx | NVKM_VMM_PAGE_HOST)
123#define NVKM_VMM_PAGE_xVHx (NVKM_VMM_PAGE_xVxx | NVKM_VMM_PAGE_HOST)
124#define NVKM_VMM_PAGE_SVHx (NVKM_VMM_PAGE_SVxx | NVKM_VMM_PAGE_HOST)
125#define NVKM_VMM_PAGE_xVxC (NVKM_VMM_PAGE_xVxx | NVKM_VMM_PAGE_COMP)
126#define NVKM_VMM_PAGE_SVxC (NVKM_VMM_PAGE_SVxx | NVKM_VMM_PAGE_COMP)
127#define NVKM_VMM_PAGE_xxHC (NVKM_VMM_PAGE_xxHx | NVKM_VMM_PAGE_COMP)
128#define NVKM_VMM_PAGE_SxHC (NVKM_VMM_PAGE_SxHx | NVKM_VMM_PAGE_COMP)
129 u8 type;
130};
131
132struct nvkm_vmm_func {
133 int (*join)(struct nvkm_vmm *, struct nvkm_memory *inst);
134 void (*part)(struct nvkm_vmm *, struct nvkm_memory *inst);
135
136 int (*aper)(enum nvkm_memory_target);
137 int (*valid)(struct nvkm_vmm *, void *argv, u32 argc,
138 struct nvkm_vmm_map *);
139 void (*flush)(struct nvkm_vmm *, int depth);
140
141 u64 page_block;
142 const struct nvkm_vmm_page page[];
143};
144
145struct nvkm_vmm_join {
146 struct nvkm_memory *inst;
147 struct list_head head;
148};
149
150int nvkm_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *,
151 u32 pd_header, u64 addr, u64 size, struct lock_class_key *,
152 const char *name, struct nvkm_vmm **);
153int nvkm_vmm_ctor(const struct nvkm_vmm_func *, struct nvkm_mmu *,
154 u32 pd_header, u64 addr, u64 size, struct lock_class_key *,
155 const char *name, struct nvkm_vmm *);
156struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr);
157int nvkm_vmm_get_locked(struct nvkm_vmm *, bool getref, bool mapref,
158 bool sparse, u8 page, u8 align, u64 size,
159 struct nvkm_vma **pvma);
160void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *);
161void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *);
162void nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma);
163
164struct nvkm_vma *nvkm_vma_tail(struct nvkm_vma *, u64 tail);
165void nvkm_vmm_node_insert(struct nvkm_vmm *, struct nvkm_vma *);
166
167int nv04_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32,
168 u64, u64, void *, u32, struct lock_class_key *,
169 const char *, struct nvkm_vmm **);
170int nv04_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
171
172int gf100_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *,
173 struct nvkm_mmu *, u64, u64, void *, u32,
174 struct lock_class_key *, const char *, struct nvkm_vmm **);
175int gf100_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base);
176int gf100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
177void gf100_vmm_part(struct nvkm_vmm *, struct nvkm_memory *);
178int gf100_vmm_aper(enum nvkm_memory_target);
179int gf100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
180void gf100_vmm_flush_(struct nvkm_vmm *, int);
181void gf100_vmm_flush(struct nvkm_vmm *, int);
182
183int gk20a_vmm_aper(enum nvkm_memory_target);
184
185int gm200_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *,
186 struct nvkm_mmu *, u64, u64, void *, u32,
187 struct lock_class_key *, const char *, struct nvkm_vmm **);
188int gm200_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base);
189int gm200_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
190
191int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
192int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *);
193void gp100_vmm_flush(struct nvkm_vmm *, int);
194
195int nv04_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
196 struct lock_class_key *, const char *, struct nvkm_vmm **);
197int nv41_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
198 struct lock_class_key *, const char *, struct nvkm_vmm **);
199int nv44_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
200 struct lock_class_key *, const char *, struct nvkm_vmm **);
201int nv50_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
202 struct lock_class_key *, const char *, struct nvkm_vmm **);
203int g84_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
204 struct lock_class_key *, const char *, struct nvkm_vmm **);
205int gf100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
206 struct lock_class_key *, const char *, struct nvkm_vmm **);
207int gk104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
208 struct lock_class_key *, const char *, struct nvkm_vmm **);
209int gk20a_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
210 struct lock_class_key *, const char *, struct nvkm_vmm **);
211int gm200_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32,
212 struct lock_class_key *, const char *,
213 struct nvkm_vmm **);
214int gm200_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
215 struct lock_class_key *, const char *,
216 struct nvkm_vmm **);
217int gm20b_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32,
218 struct lock_class_key *, const char *,
219 struct nvkm_vmm **);
220int gm20b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
221 struct lock_class_key *, const char *,
222 struct nvkm_vmm **);
223int gp100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
224 struct lock_class_key *, const char *,
225 struct nvkm_vmm **);
226int gp10b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32,
227 struct lock_class_key *, const char *,
228 struct nvkm_vmm **);
229
230#define VMM_PRINT(l,v,p,f,a...) do { \
231 struct nvkm_vmm *_vmm = (v); \
232 if (CONFIG_NOUVEAU_DEBUG >= (l) && _vmm->debug >= (l)) { \
233 nvkm_printk_(&_vmm->mmu->subdev, 0, p, "%s: "f"\n", \
234 _vmm->name, ##a); \
235 } \
236} while(0)
237#define VMM_DEBUG(v,f,a...) VMM_PRINT(NV_DBG_DEBUG, (v), info, f, ##a)
238#define VMM_TRACE(v,f,a...) VMM_PRINT(NV_DBG_TRACE, (v), info, f, ##a)
239#define VMM_SPAM(v,f,a...) VMM_PRINT(NV_DBG_SPAM , (v), dbg, f, ##a)
240
241#define VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL,BASE,SIZE,NEXT) do { \
242 nvkm_kmap((PT)->memory); \
243 while (PTEN) { \
244 u64 _ptes = ((SIZE) - MAP->off) >> MAP->page->shift; \
245 u64 _addr = ((BASE) + MAP->off); \
246 \
247 if (_ptes > PTEN) { \
248 MAP->off += PTEN << MAP->page->shift; \
249 _ptes = PTEN; \
250 } else { \
251 MAP->off = 0; \
252 NEXT; \
253 } \
254 \
255 VMM_SPAM(VMM, "ITER %08x %08x PTE(s)", PTEI, (u32)_ptes); \
256 \
257 FILL(VMM, PT, PTEI, _ptes, MAP, _addr); \
258 PTEI += _ptes; \
259 PTEN -= _ptes; \
260 }; \
261 nvkm_done((PT)->memory); \
262} while(0)
263
264#define VMM_MAP_ITER_MEM(VMM,PT,PTEI,PTEN,MAP,FILL) \
265 VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \
266 ((u64)MAP->mem->offset << NVKM_RAM_MM_SHIFT), \
267 ((u64)MAP->mem->length << NVKM_RAM_MM_SHIFT), \
268 (MAP->mem = MAP->mem->next))
269#define VMM_MAP_ITER_DMA(VMM,PT,PTEI,PTEN,MAP,FILL) \
270 VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \
271 *MAP->dma, PAGE_SIZE, MAP->dma++)
272#define VMM_MAP_ITER_SGL(VMM,PT,PTEI,PTEN,MAP,FILL) \
273 VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \
274 sg_dma_address(MAP->sgl), sg_dma_len(MAP->sgl), \
275 (MAP->sgl = sg_next(MAP->sgl)))
276
277#define VMM_FO(m,o,d,c,b) nvkm_fo##b((m)->memory, (o), (d), (c))
278#define VMM_WO(m,o,d,c,b) nvkm_wo##b((m)->memory, (o), (d))
279#define VMM_XO(m,v,o,d,c,b,fn,f,a...) do { \
280 const u32 _pteo = (o); u##b _data = (d); \
281 VMM_SPAM((v), " %010llx "f, (m)->addr + _pteo, _data, ##a); \
282 VMM_##fn((m), (m)->base + _pteo, _data, (c), b); \
283} while(0)
284
285#define VMM_WO032(m,v,o,d) VMM_XO((m),(v),(o),(d), 1, 32, WO, "%08x")
286#define VMM_FO032(m,v,o,d,c) \
287 VMM_XO((m),(v),(o),(d),(c), 32, FO, "%08x %08x", (c))
288
289#define VMM_WO064(m,v,o,d) VMM_XO((m),(v),(o),(d), 1, 64, WO, "%016llx")
290#define VMM_FO064(m,v,o,d,c) \
291 VMM_XO((m),(v),(o),(d),(c), 64, FO, "%016llx %08x", (c))
292
293#define VMM_XO128(m,v,o,lo,hi,c,f,a...) do { \
294 u32 _pteo = (o), _ptes = (c); \
295 const u64 _addr = (m)->addr + _pteo; \
296 VMM_SPAM((v), " %010llx %016llx%016llx"f, _addr, (hi), (lo), ##a); \
297 while (_ptes--) { \
298 nvkm_wo64((m)->memory, (m)->base + _pteo + 0, (lo)); \
299 nvkm_wo64((m)->memory, (m)->base + _pteo + 8, (hi)); \
300 _pteo += 0x10; \
301 } \
302} while(0)
303
304#define VMM_WO128(m,v,o,lo,hi) VMM_XO128((m),(v),(o),(lo),(hi), 1, "")
305#define VMM_FO128(m,v,o,lo,hi,c) do { \
306 nvkm_kmap((m)->memory); \
307 VMM_XO128((m),(v),(o),(lo),(hi),(c), " %08x", (c)); \
308 nvkm_done((m)->memory); \
309} while(0)
310#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c
new file mode 100644
index 000000000000..faf5a7e9265e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c
@@ -0,0 +1,403 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <subdev/fb.h>
25#include <subdev/ltc.h>
26#include <subdev/timer.h>
27
28#include <nvif/if900d.h>
29#include <nvif/unpack.h>
30
31static inline void
32gf100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
33 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
34{
35 u64 base = (addr >> 8) | map->type;
36 u64 data = base;
37
38 if (map->ctag && !(map->next & (1ULL << 44))) {
39 while (ptes--) {
40 data = base | ((map->ctag >> 1) << 44);
41 if (!(map->ctag++ & 1))
42 data |= BIT_ULL(60);
43
44 VMM_WO064(pt, vmm, ptei++ * 8, data);
45 base += map->next;
46 }
47 } else {
48 map->type += ptes * map->ctag;
49
50 while (ptes--) {
51 VMM_WO064(pt, vmm, ptei++ * 8, data);
52 data += map->next;
53 }
54 }
55}
56
57void
58gf100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
59 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
60{
61 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte);
62}
63
64void
65gf100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
66 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
67{
68 if (map->page->shift == PAGE_SHIFT) {
69 VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes);
70 nvkm_kmap(pt->memory);
71 while (ptes--) {
72 const u64 data = (*map->dma++ >> 8) | map->type;
73 VMM_WO064(pt, vmm, ptei++ * 8, data);
74 map->type += map->ctag;
75 }
76 nvkm_done(pt->memory);
77 return;
78 }
79
80 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte);
81}
82
83void
84gf100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
85 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
86{
87 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte);
88}
89
90void
91gf100_vmm_pgt_unmap(struct nvkm_vmm *vmm,
92 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
93{
94 VMM_FO064(pt, vmm, ptei * 8, 0ULL, ptes);
95}
96
97const struct nvkm_vmm_desc_func
98gf100_vmm_pgt = {
99 .unmap = gf100_vmm_pgt_unmap,
100 .mem = gf100_vmm_pgt_mem,
101 .dma = gf100_vmm_pgt_dma,
102 .sgl = gf100_vmm_pgt_sgl,
103};
104
105void
106gf100_vmm_pgd_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
107{
108 struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
109 struct nvkm_mmu_pt *pd = pgd->pt[0];
110 struct nvkm_mmu_pt *pt;
111 u64 data = 0;
112
113 if ((pt = pgt->pt[0])) {
114 switch (nvkm_memory_target(pt->memory)) {
115 case NVKM_MEM_TARGET_VRAM: data |= 1ULL << 0; break;
116 case NVKM_MEM_TARGET_HOST: data |= 2ULL << 0;
117 data |= BIT_ULL(35); /* VOL */
118 break;
119 case NVKM_MEM_TARGET_NCOH: data |= 3ULL << 0; break;
120 default:
121 WARN_ON(1);
122 return;
123 }
124 data |= pt->addr >> 8;
125 }
126
127 if ((pt = pgt->pt[1])) {
128 switch (nvkm_memory_target(pt->memory)) {
129 case NVKM_MEM_TARGET_VRAM: data |= 1ULL << 32; break;
130 case NVKM_MEM_TARGET_HOST: data |= 2ULL << 32;
131 data |= BIT_ULL(34); /* VOL */
132 break;
133 case NVKM_MEM_TARGET_NCOH: data |= 3ULL << 32; break;
134 default:
135 WARN_ON(1);
136 return;
137 }
138 data |= pt->addr << 24;
139 }
140
141 nvkm_kmap(pd->memory);
142 VMM_WO064(pd, vmm, pdei * 8, data);
143 nvkm_done(pd->memory);
144}
145
146const struct nvkm_vmm_desc_func
147gf100_vmm_pgd = {
148 .unmap = gf100_vmm_pgt_unmap,
149 .pde = gf100_vmm_pgd_pde,
150};
151
152static const struct nvkm_vmm_desc
153gf100_vmm_desc_17_12[] = {
154 { SPT, 15, 8, 0x1000, &gf100_vmm_pgt },
155 { PGD, 13, 8, 0x1000, &gf100_vmm_pgd },
156 {}
157};
158
159static const struct nvkm_vmm_desc
160gf100_vmm_desc_17_17[] = {
161 { LPT, 10, 8, 0x1000, &gf100_vmm_pgt },
162 { PGD, 13, 8, 0x1000, &gf100_vmm_pgd },
163 {}
164};
165
166static const struct nvkm_vmm_desc
167gf100_vmm_desc_16_12[] = {
168 { SPT, 14, 8, 0x1000, &gf100_vmm_pgt },
169 { PGD, 14, 8, 0x1000, &gf100_vmm_pgd },
170 {}
171};
172
173static const struct nvkm_vmm_desc
174gf100_vmm_desc_16_16[] = {
175 { LPT, 10, 8, 0x1000, &gf100_vmm_pgt },
176 { PGD, 14, 8, 0x1000, &gf100_vmm_pgd },
177 {}
178};
179
180void
181gf100_vmm_flush_(struct nvkm_vmm *vmm, int depth)
182{
183 struct nvkm_subdev *subdev = &vmm->mmu->subdev;
184 struct nvkm_device *device = subdev->device;
185 u32 type = depth << 24;
186
187 type = 0x00000001; /* PAGE_ALL */
188 if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR]))
189 type |= 0x00000004; /* HUB_ONLY */
190
191 mutex_lock(&subdev->mutex);
192 /* Looks like maybe a "free flush slots" counter, the
193 * faster you write to 0x100cbc to more it decreases.
194 */
195 nvkm_msec(device, 2000,
196 if (nvkm_rd32(device, 0x100c80) & 0x00ff0000)
197 break;
198 );
199
200 nvkm_wr32(device, 0x100cb8, vmm->pd->pt[0]->addr >> 8);
201 nvkm_wr32(device, 0x100cbc, 0x80000000 | type);
202
203 /* Wait for flush to be queued? */
204 nvkm_msec(device, 2000,
205 if (nvkm_rd32(device, 0x100c80) & 0x00008000)
206 break;
207 );
208 mutex_unlock(&subdev->mutex);
209}
210
211void
212gf100_vmm_flush(struct nvkm_vmm *vmm, int depth)
213{
214 gf100_vmm_flush_(vmm, 0);
215}
216
217int
218gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
219 struct nvkm_vmm_map *map)
220{
221 const enum nvkm_memory_target target = nvkm_memory_target(map->memory);
222 const struct nvkm_vmm_page *page = map->page;
223 const bool gm20x = page->desc->func->sparse != NULL;
224 union {
225 struct gf100_vmm_map_vn vn;
226 struct gf100_vmm_map_v0 v0;
227 } *args = argv;
228 struct nvkm_device *device = vmm->mmu->subdev.device;
229 struct nvkm_memory *memory = map->memory;
230 u8 kind, priv, ro, vol;
231 int kindn, aper, ret = -ENOSYS;
232 const u8 *kindm;
233
234 map->next = (1 << page->shift) >> 8;
235 map->type = map->ctag = 0;
236
237 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
238 vol = !!args->v0.vol;
239 ro = !!args->v0.ro;
240 priv = !!args->v0.priv;
241 kind = args->v0.kind;
242 } else
243 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
244 vol = target == NVKM_MEM_TARGET_HOST;
245 ro = 0;
246 priv = 0;
247 kind = 0x00;
248 } else {
249 VMM_DEBUG(vmm, "args");
250 return ret;
251 }
252
253 aper = vmm->func->aper(target);
254 if (WARN_ON(aper < 0))
255 return aper;
256
257 kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
258 if (kind >= kindn || kindm[kind] == 0xff) {
259 VMM_DEBUG(vmm, "kind %02x", kind);
260 return -EINVAL;
261 }
262
263 if (kindm[kind] != kind) {
264 u32 comp = (page->shift == 16 && !gm20x) ? 16 : 17;
265 u32 tags = ALIGN(nvkm_memory_size(memory), 1 << 17) >> comp;
266 if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) {
267 VMM_DEBUG(vmm, "comp %d %02x", aper, page->type);
268 return -EINVAL;
269 }
270
271 ret = nvkm_memory_tags_get(memory, device, tags,
272 nvkm_ltc_tags_clear,
273 &map->tags);
274 if (ret) {
275 VMM_DEBUG(vmm, "comp %d", ret);
276 return ret;
277 }
278
279 if (map->tags->mn) {
280 u64 tags = map->tags->mn->offset + (map->offset >> 17);
281 if (page->shift == 17 || !gm20x) {
282 map->type |= tags << 44;
283 map->ctag |= 1ULL << 44;
284 map->next |= 1ULL << 44;
285 } else {
286 map->ctag |= tags << 1 | 1;
287 }
288 } else {
289 kind = kindm[kind];
290 }
291 }
292
293 map->type |= BIT(0);
294 map->type |= (u64)priv << 1;
295 map->type |= (u64) ro << 2;
296 map->type |= (u64) vol << 32;
297 map->type |= (u64)aper << 33;
298 map->type |= (u64)kind << 36;
299 return 0;
300}
301
302int
303gf100_vmm_aper(enum nvkm_memory_target target)
304{
305 switch (target) {
306 case NVKM_MEM_TARGET_VRAM: return 0;
307 case NVKM_MEM_TARGET_HOST: return 2;
308 case NVKM_MEM_TARGET_NCOH: return 3;
309 default:
310 return -EINVAL;
311 }
312}
313
314void
315gf100_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
316{
317 nvkm_fo64(inst, 0x0200, 0x00000000, 2);
318}
319
320int
321gf100_vmm_join_(struct nvkm_vmm *vmm, struct nvkm_memory *inst, u64 base)
322{
323 struct nvkm_mmu_pt *pd = vmm->pd->pt[0];
324
325 switch (nvkm_memory_target(pd->memory)) {
326 case NVKM_MEM_TARGET_VRAM: base |= 0ULL << 0; break;
327 case NVKM_MEM_TARGET_HOST: base |= 2ULL << 0;
328 base |= BIT_ULL(2) /* VOL. */;
329 break;
330 case NVKM_MEM_TARGET_NCOH: base |= 3ULL << 0; break;
331 default:
332 WARN_ON(1);
333 return -EINVAL;
334 }
335 base |= pd->addr;
336
337 nvkm_kmap(inst);
338 nvkm_wo64(inst, 0x0200, base);
339 nvkm_wo64(inst, 0x0208, vmm->limit - 1);
340 nvkm_done(inst);
341 return 0;
342}
343
344int
345gf100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
346{
347 return gf100_vmm_join_(vmm, inst, 0);
348}
349
350static const struct nvkm_vmm_func
351gf100_vmm_17 = {
352 .join = gf100_vmm_join,
353 .part = gf100_vmm_part,
354 .aper = gf100_vmm_aper,
355 .valid = gf100_vmm_valid,
356 .flush = gf100_vmm_flush,
357 .page = {
358 { 17, &gf100_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC },
359 { 12, &gf100_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx },
360 {}
361 }
362};
363
364static const struct nvkm_vmm_func
365gf100_vmm_16 = {
366 .join = gf100_vmm_join,
367 .part = gf100_vmm_part,
368 .aper = gf100_vmm_aper,
369 .valid = gf100_vmm_valid,
370 .flush = gf100_vmm_flush,
371 .page = {
372 { 16, &gf100_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC },
373 { 12, &gf100_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx },
374 {}
375 }
376};
377
378int
379gf100_vmm_new_(const struct nvkm_vmm_func *func_16,
380 const struct nvkm_vmm_func *func_17,
381 struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
382 struct lock_class_key *key, const char *name,
383 struct nvkm_vmm **pvmm)
384{
385 switch (mmu->subdev.device->fb->page) {
386 case 16: return nv04_vmm_new_(func_16, mmu, 0, addr, size,
387 argv, argc, key, name, pvmm);
388 case 17: return nv04_vmm_new_(func_17, mmu, 0, addr, size,
389 argv, argc, key, name, pvmm);
390 default:
391 WARN_ON(1);
392 return -EINVAL;
393 }
394}
395
396int
397gf100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
398 struct lock_class_key *key, const char *name,
399 struct nvkm_vmm **pvmm)
400{
401 return gf100_vmm_new_(&gf100_vmm_16, &gf100_vmm_17, mmu, addr,
402 size, argv, argc, key, name, pvmm);
403}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c
new file mode 100644
index 000000000000..0ebb7bccfcd2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c
@@ -0,0 +1,102 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24void
25gk104_vmm_lpt_invalid(struct nvkm_vmm *vmm,
26 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
27{
28 /* VALID_FALSE + PRIV tells the MMU to ignore corresponding SPTEs. */
29 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(1) /* PRIV. */, ptes);
30}
31
32static const struct nvkm_vmm_desc_func
33gk104_vmm_lpt = {
34 .invalid = gk104_vmm_lpt_invalid,
35 .unmap = gf100_vmm_pgt_unmap,
36 .mem = gf100_vmm_pgt_mem,
37};
38
39const struct nvkm_vmm_desc
40gk104_vmm_desc_17_12[] = {
41 { SPT, 15, 8, 0x1000, &gf100_vmm_pgt },
42 { PGD, 13, 8, 0x1000, &gf100_vmm_pgd },
43 {}
44};
45
46const struct nvkm_vmm_desc
47gk104_vmm_desc_17_17[] = {
48 { LPT, 10, 8, 0x1000, &gk104_vmm_lpt },
49 { PGD, 13, 8, 0x1000, &gf100_vmm_pgd },
50 {}
51};
52
53const struct nvkm_vmm_desc
54gk104_vmm_desc_16_12[] = {
55 { SPT, 14, 8, 0x1000, &gf100_vmm_pgt },
56 { PGD, 14, 8, 0x1000, &gf100_vmm_pgd },
57 {}
58};
59
60const struct nvkm_vmm_desc
61gk104_vmm_desc_16_16[] = {
62 { LPT, 10, 8, 0x1000, &gk104_vmm_lpt },
63 { PGD, 14, 8, 0x1000, &gf100_vmm_pgd },
64 {}
65};
66
67static const struct nvkm_vmm_func
68gk104_vmm_17 = {
69 .join = gf100_vmm_join,
70 .part = gf100_vmm_part,
71 .aper = gf100_vmm_aper,
72 .valid = gf100_vmm_valid,
73 .flush = gf100_vmm_flush,
74 .page = {
75 { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC },
76 { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx },
77 {}
78 }
79};
80
81static const struct nvkm_vmm_func
82gk104_vmm_16 = {
83 .join = gf100_vmm_join,
84 .part = gf100_vmm_part,
85 .aper = gf100_vmm_aper,
86 .valid = gf100_vmm_valid,
87 .flush = gf100_vmm_flush,
88 .page = {
89 { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC },
90 { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx },
91 {}
92 }
93};
94
95int
96gk104_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
97 struct lock_class_key *key, const char *name,
98 struct nvkm_vmm **pvmm)
99{
100 return gf100_vmm_new_(&gk104_vmm_16, &gk104_vmm_17, mmu, addr,
101 size, argv, argc, key, name, pvmm);
102}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c
new file mode 100644
index 000000000000..8086994a0446
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <core/memory.h>
25
26int
27gk20a_vmm_aper(enum nvkm_memory_target target)
28{
29 switch (target) {
30 case NVKM_MEM_TARGET_NCOH: return 0;
31 default:
32 return -EINVAL;
33 }
34}
35
36static const struct nvkm_vmm_func
37gk20a_vmm_17 = {
38 .join = gf100_vmm_join,
39 .part = gf100_vmm_part,
40 .aper = gf100_vmm_aper,
41 .valid = gf100_vmm_valid,
42 .flush = gf100_vmm_flush,
43 .page = {
44 { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xxHC },
45 { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xxHx },
46 {}
47 }
48};
49
50static const struct nvkm_vmm_func
51gk20a_vmm_16 = {
52 .join = gf100_vmm_join,
53 .part = gf100_vmm_part,
54 .aper = gf100_vmm_aper,
55 .valid = gf100_vmm_valid,
56 .flush = gf100_vmm_flush,
57 .page = {
58 { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xxHC },
59 { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xxHx },
60 {}
61 }
62};
63
64int
65gk20a_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
66 struct lock_class_key *key, const char *name,
67 struct nvkm_vmm **pvmm)
68{
69 return gf100_vmm_new_(&gk20a_vmm_16, &gk20a_vmm_17, mmu, addr,
70 size, argv, argc, key, name, pvmm);
71}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c
new file mode 100644
index 000000000000..a1676a4644fe
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c
@@ -0,0 +1,185 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <nvif/ifb00d.h>
25#include <nvif/unpack.h>
26
27static void
28gm200_vmm_pgt_sparse(struct nvkm_vmm *vmm,
29 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
30{
31 /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */
32 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(32) /* VOL. */, ptes);
33}
34
35static const struct nvkm_vmm_desc_func
36gm200_vmm_spt = {
37 .unmap = gf100_vmm_pgt_unmap,
38 .sparse = gm200_vmm_pgt_sparse,
39 .mem = gf100_vmm_pgt_mem,
40 .dma = gf100_vmm_pgt_dma,
41 .sgl = gf100_vmm_pgt_sgl,
42};
43
44static const struct nvkm_vmm_desc_func
45gm200_vmm_lpt = {
46 .invalid = gk104_vmm_lpt_invalid,
47 .unmap = gf100_vmm_pgt_unmap,
48 .sparse = gm200_vmm_pgt_sparse,
49 .mem = gf100_vmm_pgt_mem,
50};
51
52static void
53gm200_vmm_pgd_sparse(struct nvkm_vmm *vmm,
54 struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
55{
56 /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */
57 VMM_FO064(pt, vmm, pdei * 8, BIT_ULL(35) /* VOL_BIG. */, pdes);
58}
59
60static const struct nvkm_vmm_desc_func
61gm200_vmm_pgd = {
62 .unmap = gf100_vmm_pgt_unmap,
63 .sparse = gm200_vmm_pgd_sparse,
64 .pde = gf100_vmm_pgd_pde,
65};
66
67const struct nvkm_vmm_desc
68gm200_vmm_desc_17_12[] = {
69 { SPT, 15, 8, 0x1000, &gm200_vmm_spt },
70 { PGD, 13, 8, 0x1000, &gm200_vmm_pgd },
71 {}
72};
73
74const struct nvkm_vmm_desc
75gm200_vmm_desc_17_17[] = {
76 { LPT, 10, 8, 0x1000, &gm200_vmm_lpt },
77 { PGD, 13, 8, 0x1000, &gm200_vmm_pgd },
78 {}
79};
80
81const struct nvkm_vmm_desc
82gm200_vmm_desc_16_12[] = {
83 { SPT, 14, 8, 0x1000, &gm200_vmm_spt },
84 { PGD, 14, 8, 0x1000, &gm200_vmm_pgd },
85 {}
86};
87
88const struct nvkm_vmm_desc
89gm200_vmm_desc_16_16[] = {
90 { LPT, 10, 8, 0x1000, &gm200_vmm_lpt },
91 { PGD, 14, 8, 0x1000, &gm200_vmm_pgd },
92 {}
93};
94
95int
96gm200_vmm_join_(struct nvkm_vmm *vmm, struct nvkm_memory *inst, u64 base)
97{
98 if (vmm->func->page[1].shift == 16)
99 base |= BIT_ULL(11);
100 return gf100_vmm_join_(vmm, inst, base);
101}
102
103int
104gm200_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
105{
106 return gm200_vmm_join_(vmm, inst, 0);
107}
108
109static const struct nvkm_vmm_func
110gm200_vmm_17 = {
111 .join = gm200_vmm_join,
112 .part = gf100_vmm_part,
113 .aper = gf100_vmm_aper,
114 .valid = gf100_vmm_valid,
115 .flush = gf100_vmm_flush,
116 .page = {
117 { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx },
118 { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SVxC },
119 { 12, &gm200_vmm_desc_17_12[0], NVKM_VMM_PAGE_SVHx },
120 {}
121 }
122};
123
124static const struct nvkm_vmm_func
125gm200_vmm_16 = {
126 .join = gm200_vmm_join,
127 .part = gf100_vmm_part,
128 .aper = gf100_vmm_aper,
129 .valid = gf100_vmm_valid,
130 .flush = gf100_vmm_flush,
131 .page = {
132 { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx },
133 { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SVxC },
134 { 12, &gm200_vmm_desc_16_12[0], NVKM_VMM_PAGE_SVHx },
135 {}
136 }
137};
138
139int
140gm200_vmm_new_(const struct nvkm_vmm_func *func_16,
141 const struct nvkm_vmm_func *func_17,
142 struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
143 struct lock_class_key *key, const char *name,
144 struct nvkm_vmm **pvmm)
145{
146 const struct nvkm_vmm_func *func;
147 union {
148 struct gm200_vmm_vn vn;
149 struct gm200_vmm_v0 v0;
150 } *args = argv;
151 int ret = -ENOSYS;
152
153 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
154 switch (args->v0.bigpage) {
155 case 16: func = func_16; break;
156 case 17: func = func_17; break;
157 default:
158 return -EINVAL;
159 }
160 } else
161 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
162 func = func_17;
163 } else
164 return ret;
165
166 return nvkm_vmm_new_(func, mmu, 0, addr, size, key, name, pvmm);
167}
168
169int
170gm200_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
171 struct lock_class_key *key, const char *name,
172 struct nvkm_vmm **pvmm)
173{
174 return gm200_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr,
175 size, argv, argc, key, name, pvmm);
176}
177
178int
179gm200_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size,
180 void *argv, u32 argc, struct lock_class_key *key,
181 const char *name, struct nvkm_vmm **pvmm)
182{
183 return gf100_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr,
184 size, argv, argc, key, name, pvmm);
185}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c
new file mode 100644
index 000000000000..64d4b6cff8dd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24static const struct nvkm_vmm_func
25gm20b_vmm_17 = {
26 .join = gm200_vmm_join,
27 .part = gf100_vmm_part,
28 .aper = gk20a_vmm_aper,
29 .valid = gf100_vmm_valid,
30 .flush = gf100_vmm_flush,
31 .page = {
32 { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx },
33 { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SxHC },
34 { 12, &gm200_vmm_desc_17_12[0], NVKM_VMM_PAGE_SxHx },
35 {}
36 }
37};
38
39static const struct nvkm_vmm_func
40gm20b_vmm_16 = {
41 .join = gm200_vmm_join,
42 .part = gf100_vmm_part,
43 .aper = gk20a_vmm_aper,
44 .valid = gf100_vmm_valid,
45 .flush = gf100_vmm_flush,
46 .page = {
47 { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx },
48 { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SxHC },
49 { 12, &gm200_vmm_desc_16_12[0], NVKM_VMM_PAGE_SxHx },
50 {}
51 }
52};
53
54int
55gm20b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
56 struct lock_class_key *key, const char *name,
57 struct nvkm_vmm **pvmm)
58{
59 return gm200_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr,
60 size, argv, argc, key, name, pvmm);
61}
62
63int
64gm20b_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size,
65 void *argv, u32 argc, struct lock_class_key *key,
66 const char *name, struct nvkm_vmm **pvmm)
67{
68 return gf100_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr,
69 size, argv, argc, key, name, pvmm);
70}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
new file mode 100644
index 000000000000..059fafe0e771
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
@@ -0,0 +1,347 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <subdev/fb.h>
25#include <subdev/ltc.h>
26
27#include <nvif/ifc00d.h>
28#include <nvif/unpack.h>
29
30static inline void
31gp100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
32 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
33{
34 u64 data = (addr >> 4) | map->type;
35
36 map->type += ptes * map->ctag;
37
38 while (ptes--) {
39 VMM_WO064(pt, vmm, ptei++ * 8, data);
40 data += map->next;
41 }
42}
43
44static void
45gp100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
46 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
47{
48 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte);
49}
50
51static void
52gp100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
53 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
54{
55 if (map->page->shift == PAGE_SHIFT) {
56 VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes);
57 nvkm_kmap(pt->memory);
58 while (ptes--) {
59 const u64 data = (*map->dma++ >> 4) | map->type;
60 VMM_WO064(pt, vmm, ptei++ * 8, data);
61 map->type += map->ctag;
62 }
63 nvkm_done(pt->memory);
64 return;
65 }
66
67 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte);
68}
69
70static void
71gp100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
72 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
73{
74 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte);
75}
76
77static void
78gp100_vmm_pgt_sparse(struct nvkm_vmm *vmm,
79 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
80{
81 /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */
82 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(3) /* VOL. */, ptes);
83}
84
85static const struct nvkm_vmm_desc_func
86gp100_vmm_desc_spt = {
87 .unmap = gf100_vmm_pgt_unmap,
88 .sparse = gp100_vmm_pgt_sparse,
89 .mem = gp100_vmm_pgt_mem,
90 .dma = gp100_vmm_pgt_dma,
91 .sgl = gp100_vmm_pgt_sgl,
92};
93
94static void
95gp100_vmm_lpt_invalid(struct nvkm_vmm *vmm,
96 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
97{
98 /* VALID_FALSE + PRIV tells the MMU to ignore corresponding SPTEs. */
99 VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(5) /* PRIV. */, ptes);
100}
101
102static const struct nvkm_vmm_desc_func
103gp100_vmm_desc_lpt = {
104 .invalid = gp100_vmm_lpt_invalid,
105 .unmap = gf100_vmm_pgt_unmap,
106 .sparse = gp100_vmm_pgt_sparse,
107 .mem = gp100_vmm_pgt_mem,
108};
109
110static inline void
111gp100_vmm_pd0_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
112 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
113{
114 u64 data = (addr >> 4) | map->type;
115
116 map->type += ptes * map->ctag;
117
118 while (ptes--) {
119 VMM_WO128(pt, vmm, ptei++ * 0x10, data, 0ULL);
120 data += map->next;
121 }
122}
123
124static void
125gp100_vmm_pd0_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
126 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
127{
128 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pd0_pte);
129}
130
131static inline bool
132gp100_vmm_pde(struct nvkm_mmu_pt *pt, u64 *data)
133{
134 switch (nvkm_memory_target(pt->memory)) {
135 case NVKM_MEM_TARGET_VRAM: *data |= 1ULL << 1; break;
136 case NVKM_MEM_TARGET_HOST: *data |= 2ULL << 1;
137 *data |= BIT_ULL(3); /* VOL. */
138 break;
139 case NVKM_MEM_TARGET_NCOH: *data |= 3ULL << 1; break;
140 default:
141 WARN_ON(1);
142 return false;
143 }
144 *data |= pt->addr >> 4;
145 return true;
146}
147
148static void
149gp100_vmm_pd0_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
150{
151 struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
152 struct nvkm_mmu_pt *pd = pgd->pt[0];
153 u64 data[2] = {};
154
155 if (pgt->pt[0] && !gp100_vmm_pde(pgt->pt[0], &data[0]))
156 return;
157 if (pgt->pt[1] && !gp100_vmm_pde(pgt->pt[1], &data[1]))
158 return;
159
160 nvkm_kmap(pd->memory);
161 VMM_WO128(pd, vmm, pdei * 0x10, data[0], data[1]);
162 nvkm_done(pd->memory);
163}
164
165static void
166gp100_vmm_pd0_sparse(struct nvkm_vmm *vmm,
167 struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
168{
169 /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */
170 VMM_FO128(pt, vmm, pdei * 0x10, BIT_ULL(3) /* VOL_BIG. */, 0ULL, pdes);
171}
172
173static void
174gp100_vmm_pd0_unmap(struct nvkm_vmm *vmm,
175 struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
176{
177 VMM_FO128(pt, vmm, pdei * 0x10, 0ULL, 0ULL, pdes);
178}
179
180static const struct nvkm_vmm_desc_func
181gp100_vmm_desc_pd0 = {
182 .unmap = gp100_vmm_pd0_unmap,
183 .sparse = gp100_vmm_pd0_sparse,
184 .pde = gp100_vmm_pd0_pde,
185 .mem = gp100_vmm_pd0_mem,
186};
187
188static void
189gp100_vmm_pd1_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
190{
191 struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
192 struct nvkm_mmu_pt *pd = pgd->pt[0];
193 u64 data = 0;
194
195 if (!gp100_vmm_pde(pgt->pt[0], &data))
196 return;
197
198 nvkm_kmap(pd->memory);
199 VMM_WO064(pd, vmm, pdei * 8, data);
200 nvkm_done(pd->memory);
201}
202
203static const struct nvkm_vmm_desc_func
204gp100_vmm_desc_pd1 = {
205 .unmap = gf100_vmm_pgt_unmap,
206 .sparse = gp100_vmm_pgt_sparse,
207 .pde = gp100_vmm_pd1_pde,
208};
209
210const struct nvkm_vmm_desc
211gp100_vmm_desc_16[] = {
212 { LPT, 5, 8, 0x0100, &gp100_vmm_desc_lpt },
213 { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 },
214 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 },
215 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 },
216 { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 },
217 {}
218};
219
220const struct nvkm_vmm_desc
221gp100_vmm_desc_12[] = {
222 { SPT, 9, 8, 0x1000, &gp100_vmm_desc_spt },
223 { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 },
224 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 },
225 { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 },
226 { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 },
227 {}
228};
229
230int
231gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
232 struct nvkm_vmm_map *map)
233{
234 const enum nvkm_memory_target target = nvkm_memory_target(map->memory);
235 const struct nvkm_vmm_page *page = map->page;
236 union {
237 struct gp100_vmm_map_vn vn;
238 struct gp100_vmm_map_v0 v0;
239 } *args = argv;
240 struct nvkm_device *device = vmm->mmu->subdev.device;
241 struct nvkm_memory *memory = map->memory;
242 u8 kind, priv, ro, vol;
243 int kindn, aper, ret = -ENOSYS;
244 const u8 *kindm;
245
246 map->next = (1ULL << page->shift) >> 4;
247 map->type = 0;
248
249 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
250 vol = !!args->v0.vol;
251 ro = !!args->v0.ro;
252 priv = !!args->v0.priv;
253 kind = args->v0.kind;
254 } else
255 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
256 vol = target == NVKM_MEM_TARGET_HOST;
257 ro = 0;
258 priv = 0;
259 kind = 0x00;
260 } else {
261 VMM_DEBUG(vmm, "args");
262 return ret;
263 }
264
265 aper = vmm->func->aper(target);
266 if (WARN_ON(aper < 0))
267 return aper;
268
269 kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
270 if (kind >= kindn || kindm[kind] == 0xff) {
271 VMM_DEBUG(vmm, "kind %02x", kind);
272 return -EINVAL;
273 }
274
275 if (kindm[kind] != kind) {
276 u64 tags = nvkm_memory_size(memory) >> 16;
277 if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) {
278 VMM_DEBUG(vmm, "comp %d %02x", aper, page->type);
279 return -EINVAL;
280 }
281
282 ret = nvkm_memory_tags_get(memory, device, tags,
283 nvkm_ltc_tags_clear,
284 &map->tags);
285 if (ret) {
286 VMM_DEBUG(vmm, "comp %d", ret);
287 return ret;
288 }
289
290 if (map->tags->mn) {
291 tags = map->tags->mn->offset + (map->offset >> 16);
292 map->ctag |= ((1ULL << page->shift) >> 16) << 36;
293 map->type |= tags << 36;
294 map->next |= map->ctag;
295 } else {
296 kind = kindm[kind];
297 }
298 }
299
300 map->type |= BIT(0);
301 map->type |= (u64)aper << 1;
302 map->type |= (u64) vol << 3;
303 map->type |= (u64)priv << 5;
304 map->type |= (u64) ro << 6;
305 map->type |= (u64)kind << 56;
306 return 0;
307}
308
309void
310gp100_vmm_flush(struct nvkm_vmm *vmm, int depth)
311{
312 gf100_vmm_flush_(vmm, 5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth);
313}
314
315int
316gp100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
317{
318 const u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11); /* 64KiB */
319 return gf100_vmm_join_(vmm, inst, base);
320}
321
322static const struct nvkm_vmm_func
323gp100_vmm = {
324 .join = gp100_vmm_join,
325 .part = gf100_vmm_part,
326 .aper = gf100_vmm_aper,
327 .valid = gp100_vmm_valid,
328 .flush = gp100_vmm_flush,
329 .page = {
330 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx },
331 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx },
332 { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx },
333 { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxC },
334 { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxC },
335 { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx },
336 {}
337 }
338};
339
340int
341gp100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
342 struct lock_class_key *key, const char *name,
343 struct nvkm_vmm **pvmm)
344{
345 return nv04_vmm_new_(&gp100_vmm, mmu, 0, addr, size,
346 argv, argc, key, name, pvmm);
347}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c
new file mode 100644
index 000000000000..3dcc6bddb32f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c
@@ -0,0 +1,49 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24static const struct nvkm_vmm_func
25gp10b_vmm = {
26 .join = gp100_vmm_join,
27 .part = gf100_vmm_part,
28 .aper = gk20a_vmm_aper,
29 .valid = gp100_vmm_valid,
30 .flush = gp100_vmm_flush,
31 .page = {
32 { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx },
33 { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx },
34 { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx },
35 { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SxHC },
36 { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SxHC },
37 { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SxHx },
38 {}
39 }
40};
41
42int
43gp10b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
44 struct lock_class_key *key, const char *name,
45 struct nvkm_vmm **pvmm)
46{
47 return nv04_vmm_new_(&gp10b_vmm, mmu, 0, addr, size,
48 argv, argc, key, name, pvmm);
49}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c
new file mode 100644
index 000000000000..0cab1ffc9f64
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <nvif/if000d.h>
25#include <nvif/unpack.h>
26
27static inline void
28nv04_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
29 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
30{
31 u32 data = addr | 0x00000003; /* PRESENT, RW. */
32 while (ptes--) {
33 VMM_WO032(pt, vmm, 8 + ptei++ * 4, data);
34 data += 0x00001000;
35 }
36}
37
38static void
39nv04_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
40 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
41{
42 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv04_vmm_pgt_pte);
43}
44
45static void
46nv04_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
47 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
48{
49#if PAGE_SHIFT == 12
50 nvkm_kmap(pt->memory);
51 while (ptes--)
52 VMM_WO032(pt, vmm, 8 + (ptei++ * 4), *map->dma++ | 0x00000003);
53 nvkm_done(pt->memory);
54#else
55 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv04_vmm_pgt_pte);
56#endif
57}
58
59static void
60nv04_vmm_pgt_unmap(struct nvkm_vmm *vmm,
61 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
62{
63 VMM_FO032(pt, vmm, 8 + (ptei * 4), 0, ptes);
64}
65
66static const struct nvkm_vmm_desc_func
67nv04_vmm_desc_pgt = {
68 .unmap = nv04_vmm_pgt_unmap,
69 .dma = nv04_vmm_pgt_dma,
70 .sgl = nv04_vmm_pgt_sgl,
71};
72
73static const struct nvkm_vmm_desc
74nv04_vmm_desc_12[] = {
75 { PGT, 15, 4, 0x1000, &nv04_vmm_desc_pgt },
76 {}
77};
78
79int
80nv04_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
81 struct nvkm_vmm_map *map)
82{
83 union {
84 struct nv04_vmm_map_vn vn;
85 } *args = argv;
86 int ret = -ENOSYS;
87 if ((ret = nvif_unvers(ret, &argv, &argc, args->vn)))
88 VMM_DEBUG(vmm, "args");
89 return ret;
90}
91
92static const struct nvkm_vmm_func
93nv04_vmm = {
94 .valid = nv04_vmm_valid,
95 .page = {
96 { 12, &nv04_vmm_desc_12[0], NVKM_VMM_PAGE_HOST },
97 {}
98 }
99};
100
101int
102nv04_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu,
103 u32 pd_header, u64 addr, u64 size, void *argv, u32 argc,
104 struct lock_class_key *key, const char *name,
105 struct nvkm_vmm **pvmm)
106{
107 union {
108 struct nv04_vmm_vn vn;
109 } *args = argv;
110 int ret;
111
112 ret = nvkm_vmm_new_(func, mmu, pd_header, addr, size, key, name, pvmm);
113 if (ret)
114 return ret;
115
116 return nvif_unvers(-ENOSYS, &argv, &argc, args->vn);
117}
118
119int
120nv04_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
121 struct lock_class_key *key, const char *name,
122 struct nvkm_vmm **pvmm)
123{
124 struct nvkm_memory *mem;
125 struct nvkm_vmm *vmm;
126 int ret;
127
128 ret = nv04_vmm_new_(&nv04_vmm, mmu, 8, addr, size,
129 argv, argc, key, name, &vmm);
130 *pvmm = vmm;
131 if (ret)
132 return ret;
133
134 mem = vmm->pd->pt[0]->memory;
135 nvkm_kmap(mem);
136 nvkm_wo32(mem, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */
137 nvkm_wo32(mem, 0x00004, vmm->limit - 1);
138 nvkm_done(mem);
139 return 0;
140}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c
new file mode 100644
index 000000000000..b595f130e573
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c
@@ -0,0 +1,113 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <subdev/timer.h>
25
26static void
27nv41_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
28 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
29{
30 u32 data = (addr >> 7) | 0x00000001; /* VALID. */
31 while (ptes--) {
32 VMM_WO032(pt, vmm, ptei++ * 4, data);
33 data += 0x00000020;
34 }
35}
36
37static void
38nv41_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
39 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
40{
41 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte);
42}
43
44static void
45nv41_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
46 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
47{
48#if PAGE_SHIFT == 12
49 nvkm_kmap(pt->memory);
50 while (ptes--) {
51 const u32 data = (*map->dma++ >> 7) | 0x00000001;
52 VMM_WO032(pt, vmm, ptei++ * 4, data);
53 }
54 nvkm_done(pt->memory);
55#else
56 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte);
57#endif
58}
59
60static void
61nv41_vmm_pgt_unmap(struct nvkm_vmm *vmm,
62 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
63{
64 VMM_FO032(pt, vmm, ptei * 4, 0, ptes);
65}
66
67static const struct nvkm_vmm_desc_func
68nv41_vmm_desc_pgt = {
69 .unmap = nv41_vmm_pgt_unmap,
70 .dma = nv41_vmm_pgt_dma,
71 .sgl = nv41_vmm_pgt_sgl,
72};
73
74static const struct nvkm_vmm_desc
75nv41_vmm_desc_12[] = {
76 { PGT, 17, 4, 0x1000, &nv41_vmm_desc_pgt },
77 {}
78};
79
80static void
81nv41_vmm_flush(struct nvkm_vmm *vmm, int level)
82{
83 struct nvkm_subdev *subdev = &vmm->mmu->subdev;
84 struct nvkm_device *device = subdev->device;
85
86 mutex_lock(&subdev->mutex);
87 nvkm_wr32(device, 0x100810, 0x00000022);
88 nvkm_msec(device, 2000,
89 if (nvkm_rd32(device, 0x100810) & 0x00000020)
90 break;
91 );
92 nvkm_wr32(device, 0x100810, 0x00000000);
93 mutex_unlock(&subdev->mutex);
94}
95
96static const struct nvkm_vmm_func
97nv41_vmm = {
98 .valid = nv04_vmm_valid,
99 .flush = nv41_vmm_flush,
100 .page = {
101 { 12, &nv41_vmm_desc_12[0], NVKM_VMM_PAGE_HOST },
102 {}
103 }
104};
105
106int
107nv41_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
108 struct lock_class_key *key, const char *name,
109 struct nvkm_vmm **pvmm)
110{
111 return nv04_vmm_new_(&nv41_vmm, mmu, 0, addr, size,
112 argv, argc, key, name, pvmm);
113}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c
new file mode 100644
index 000000000000..b834e4352334
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c
@@ -0,0 +1,230 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <subdev/timer.h>
25
26static void
27nv44_vmm_pgt_fill(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
28 dma_addr_t *list, u32 ptei, u32 ptes)
29{
30 u32 pteo = (ptei << 2) & ~0x0000000f;
31 u32 tmp[4];
32
33 tmp[0] = nvkm_ro32(pt->memory, pteo + 0x0);
34 tmp[1] = nvkm_ro32(pt->memory, pteo + 0x4);
35 tmp[2] = nvkm_ro32(pt->memory, pteo + 0x8);
36 tmp[3] = nvkm_ro32(pt->memory, pteo + 0xc);
37
38 while (ptes--) {
39 u32 addr = (list ? *list++ : vmm->null) >> 12;
40 switch (ptei++ & 0x3) {
41 case 0:
42 tmp[0] &= ~0x07ffffff;
43 tmp[0] |= addr;
44 break;
45 case 1:
46 tmp[0] &= ~0xf8000000;
47 tmp[0] |= addr << 27;
48 tmp[1] &= ~0x003fffff;
49 tmp[1] |= addr >> 5;
50 break;
51 case 2:
52 tmp[1] &= ~0xffc00000;
53 tmp[1] |= addr << 22;
54 tmp[2] &= ~0x0001ffff;
55 tmp[2] |= addr >> 10;
56 break;
57 case 3:
58 tmp[2] &= ~0xfffe0000;
59 tmp[2] |= addr << 17;
60 tmp[3] &= ~0x00000fff;
61 tmp[3] |= addr >> 15;
62 break;
63 }
64 }
65
66 VMM_WO032(pt, vmm, pteo + 0x0, tmp[0]);
67 VMM_WO032(pt, vmm, pteo + 0x4, tmp[1]);
68 VMM_WO032(pt, vmm, pteo + 0x8, tmp[2]);
69 VMM_WO032(pt, vmm, pteo + 0xc, tmp[3] | 0x40000000);
70}
71
72static void
73nv44_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
74 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
75{
76 dma_addr_t tmp[4], i;
77
78 if (ptei & 3) {
79 const u32 pten = min(ptes, 4 - (ptei & 3));
80 for (i = 0; i < pten; i++, addr += 0x1000)
81 tmp[i] = addr;
82 nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, pten);
83 ptei += pten;
84 ptes -= pten;
85 }
86
87 while (ptes >= 4) {
88 for (i = 0; i < 4; i++, addr += 0x1000)
89 tmp[i] = addr >> 12;
90 VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >> 0 | tmp[1] << 27);
91 VMM_WO032(pt, vmm, ptei++ * 4, tmp[1] >> 5 | tmp[2] << 22);
92 VMM_WO032(pt, vmm, ptei++ * 4, tmp[2] >> 10 | tmp[3] << 17);
93 VMM_WO032(pt, vmm, ptei++ * 4, tmp[3] >> 15 | 0x40000000);
94 ptes -= 4;
95 }
96
97 if (ptes) {
98 for (i = 0; i < ptes; i++, addr += 0x1000)
99 tmp[i] = addr;
100 nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, ptes);
101 }
102}
103
104static void
105nv44_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
106 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
107{
108 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv44_vmm_pgt_pte);
109}
110
111static void
112nv44_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
113 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
114{
115#if PAGE_SHIFT == 12
116 nvkm_kmap(pt->memory);
117 if (ptei & 3) {
118 const u32 pten = min(ptes, 4 - (ptei & 3));
119 nv44_vmm_pgt_fill(vmm, pt, map->dma, ptei, pten);
120 ptei += pten;
121 ptes -= pten;
122 map->dma += pten;
123 }
124
125 while (ptes >= 4) {
126 u32 tmp[4], i;
127 for (i = 0; i < 4; i++)
128 tmp[i] = *map->dma++ >> 12;
129 VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >> 0 | tmp[1] << 27);
130 VMM_WO032(pt, vmm, ptei++ * 4, tmp[1] >> 5 | tmp[2] << 22);
131 VMM_WO032(pt, vmm, ptei++ * 4, tmp[2] >> 10 | tmp[3] << 17);
132 VMM_WO032(pt, vmm, ptei++ * 4, tmp[3] >> 15 | 0x40000000);
133 ptes -= 4;
134 }
135
136 if (ptes) {
137 nv44_vmm_pgt_fill(vmm, pt, map->dma, ptei, ptes);
138 map->dma += ptes;
139 }
140 nvkm_done(pt->memory);
141#else
142 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv44_vmm_pgt_pte);
143#endif
144}
145
146static void
147nv44_vmm_pgt_unmap(struct nvkm_vmm *vmm,
148 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
149{
150 nvkm_kmap(pt->memory);
151 if (ptei & 3) {
152 const u32 pten = min(ptes, 4 - (ptei & 3));
153 nv44_vmm_pgt_fill(vmm, pt, NULL, ptei, pten);
154 ptei += pten;
155 ptes -= pten;
156 }
157
158 while (ptes > 4) {
159 VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000);
160 VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000);
161 VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000);
162 VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000);
163 ptes -= 4;
164 }
165
166 if (ptes)
167 nv44_vmm_pgt_fill(vmm, pt, NULL, ptei, ptes);
168 nvkm_done(pt->memory);
169}
170
171static const struct nvkm_vmm_desc_func
172nv44_vmm_desc_pgt = {
173 .unmap = nv44_vmm_pgt_unmap,
174 .dma = nv44_vmm_pgt_dma,
175 .sgl = nv44_vmm_pgt_sgl,
176};
177
178static const struct nvkm_vmm_desc
179nv44_vmm_desc_12[] = {
180 { PGT, 17, 4, 0x80000, &nv44_vmm_desc_pgt },
181 {}
182};
183
184static void
185nv44_vmm_flush(struct nvkm_vmm *vmm, int level)
186{
187 struct nvkm_device *device = vmm->mmu->subdev.device;
188 nvkm_wr32(device, 0x100814, vmm->limit - 4096);
189 nvkm_wr32(device, 0x100808, 0x000000020);
190 nvkm_msec(device, 2000,
191 if (nvkm_rd32(device, 0x100808) & 0x00000001)
192 break;
193 );
194 nvkm_wr32(device, 0x100808, 0x00000000);
195}
196
197static const struct nvkm_vmm_func
198nv44_vmm = {
199 .valid = nv04_vmm_valid,
200 .flush = nv44_vmm_flush,
201 .page = {
202 { 12, &nv44_vmm_desc_12[0], NVKM_VMM_PAGE_HOST },
203 {}
204 }
205};
206
207int
208nv44_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
209 struct lock_class_key *key, const char *name,
210 struct nvkm_vmm **pvmm)
211{
212 struct nvkm_subdev *subdev = &mmu->subdev;
213 struct nvkm_vmm *vmm;
214 int ret;
215
216 ret = nv04_vmm_new_(&nv44_vmm, mmu, 0, addr, size,
217 argv, argc, key, name, &vmm);
218 *pvmm = vmm;
219 if (ret)
220 return ret;
221
222 vmm->nullp = dma_alloc_coherent(subdev->device->dev, 16 * 1024,
223 &vmm->null, GFP_KERNEL);
224 if (!vmm->nullp) {
225 nvkm_warn(subdev, "unable to allocate dummy pages\n");
226 vmm->null = 0;
227 }
228
229 return 0;
230}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c
new file mode 100644
index 000000000000..863a2edd9861
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c
@@ -0,0 +1,385 @@
1/*
2 * Copyright 2017 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "vmm.h"
23
24#include <subdev/fb.h>
25#include <subdev/timer.h>
26#include <engine/gr.h>
27
28#include <nvif/if500d.h>
29#include <nvif/unpack.h>
30
31static inline void
32nv50_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
33 u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
34{
35 u64 next = addr | map->type, data;
36 u32 pten;
37 int log2blk;
38
39 map->type += ptes * map->ctag;
40
41 while (ptes) {
42 for (log2blk = 7; log2blk >= 0; log2blk--) {
43 pten = 1 << log2blk;
44 if (ptes >= pten && IS_ALIGNED(ptei, pten))
45 break;
46 }
47
48 data = next | (log2blk << 7);
49 next += pten * map->next;
50 ptes -= pten;
51
52 while (pten--)
53 VMM_WO064(pt, vmm, ptei++ * 8, data);
54 }
55}
56
57static void
58nv50_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
59 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
60{
61 VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte);
62}
63
64static void
65nv50_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
66 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
67{
68 if (map->page->shift == PAGE_SHIFT) {
69 VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes);
70 nvkm_kmap(pt->memory);
71 while (ptes--) {
72 const u64 data = *map->dma++ | map->type;
73 VMM_WO064(pt, vmm, ptei++ * 8, data);
74 map->type += map->ctag;
75 }
76 nvkm_done(pt->memory);
77 return;
78 }
79
80 VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte);
81}
82
83static void
84nv50_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
85 u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
86{
87 VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte);
88}
89
90static void
91nv50_vmm_pgt_unmap(struct nvkm_vmm *vmm,
92 struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
93{
94 VMM_FO064(pt, vmm, ptei * 8, 0ULL, ptes);
95}
96
97static const struct nvkm_vmm_desc_func
98nv50_vmm_pgt = {
99 .unmap = nv50_vmm_pgt_unmap,
100 .mem = nv50_vmm_pgt_mem,
101 .dma = nv50_vmm_pgt_dma,
102 .sgl = nv50_vmm_pgt_sgl,
103};
104
105static bool
106nv50_vmm_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgt, u64 *pdata)
107{
108 struct nvkm_mmu_pt *pt;
109 u64 data = 0xdeadcafe00000000ULL;
110 if (pgt && (pt = pgt->pt[0])) {
111 switch (pgt->page) {
112 case 16: data = 0x00000001; break;
113 case 12: data = 0x00000003;
114 switch (nvkm_memory_size(pt->memory)) {
115 case 0x100000: data |= 0x00000000; break;
116 case 0x040000: data |= 0x00000020; break;
117 case 0x020000: data |= 0x00000040; break;
118 case 0x010000: data |= 0x00000060; break;
119 default:
120 WARN_ON(1);
121 return false;
122 }
123 break;
124 default:
125 WARN_ON(1);
126 return false;
127 }
128
129 switch (nvkm_memory_target(pt->memory)) {
130 case NVKM_MEM_TARGET_VRAM: data |= 0x00000000; break;
131 case NVKM_MEM_TARGET_HOST: data |= 0x00000008; break;
132 case NVKM_MEM_TARGET_NCOH: data |= 0x0000000c; break;
133 default:
134 WARN_ON(1);
135 return false;
136 }
137
138 data |= pt->addr;
139 }
140 *pdata = data;
141 return true;
142}
143
144static void
145nv50_vmm_pgd_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
146{
147 struct nvkm_vmm_join *join;
148 u32 pdeo = vmm->mmu->func->vmm.pd_offset + (pdei * 8);
149 u64 data;
150
151 if (!nv50_vmm_pde(vmm, pgd->pde[pdei], &data))
152 return;
153
154 list_for_each_entry(join, &vmm->join, head) {
155 nvkm_kmap(join->inst);
156 nvkm_wo64(join->inst, pdeo, data);
157 nvkm_done(join->inst);
158 }
159}
160
161static const struct nvkm_vmm_desc_func
162nv50_vmm_pgd = {
163 .pde = nv50_vmm_pgd_pde,
164};
165
166static const struct nvkm_vmm_desc
167nv50_vmm_desc_12[] = {
168 { PGT, 17, 8, 0x1000, &nv50_vmm_pgt },
169 { PGD, 11, 0, 0x0000, &nv50_vmm_pgd },
170 {}
171};
172
173static const struct nvkm_vmm_desc
174nv50_vmm_desc_16[] = {
175 { PGT, 13, 8, 0x1000, &nv50_vmm_pgt },
176 { PGD, 11, 0, 0x0000, &nv50_vmm_pgd },
177 {}
178};
179
180static void
181nv50_vmm_flush(struct nvkm_vmm *vmm, int level)
182{
183 struct nvkm_subdev *subdev = &vmm->mmu->subdev;
184 struct nvkm_device *device = subdev->device;
185 int i, id;
186
187 mutex_lock(&subdev->mutex);
188 for (i = 0; i < NVKM_SUBDEV_NR; i++) {
189 if (!atomic_read(&vmm->engref[i]))
190 continue;
191
192 /* unfortunate hw bug workaround... */
193 if (i == NVKM_ENGINE_GR && device->gr) {
194 int ret = nvkm_gr_tlb_flush(device->gr);
195 if (ret != -ENODEV)
196 continue;
197 }
198
199 switch (i) {
200 case NVKM_ENGINE_GR : id = 0x00; break;
201 case NVKM_ENGINE_VP :
202 case NVKM_ENGINE_MSPDEC: id = 0x01; break;
203 case NVKM_SUBDEV_BAR : id = 0x06; break;
204 case NVKM_ENGINE_MSPPP :
205 case NVKM_ENGINE_MPEG : id = 0x08; break;
206 case NVKM_ENGINE_BSP :
207 case NVKM_ENGINE_MSVLD : id = 0x09; break;
208 case NVKM_ENGINE_CIPHER:
209 case NVKM_ENGINE_SEC : id = 0x0a; break;
210 case NVKM_ENGINE_CE0 : id = 0x0d; break;
211 default:
212 continue;
213 }
214
215 nvkm_wr32(device, 0x100c80, (id << 16) | 1);
216 if (nvkm_msec(device, 2000,
217 if (!(nvkm_rd32(device, 0x100c80) & 0x00000001))
218 break;
219 ) < 0)
220 nvkm_error(subdev, "%s mmu invalidate timeout\n",
221 nvkm_subdev_name[i]);
222 }
223 mutex_unlock(&subdev->mutex);
224}
225
226static int
227nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
228 struct nvkm_vmm_map *map)
229{
230 const struct nvkm_vmm_page *page = map->page;
231 union {
232 struct nv50_vmm_map_vn vn;
233 struct nv50_vmm_map_v0 v0;
234 } *args = argv;
235 struct nvkm_device *device = vmm->mmu->subdev.device;
236 struct nvkm_ram *ram = device->fb->ram;
237 struct nvkm_memory *memory = map->memory;
238 u8 aper, kind, comp, priv, ro;
239 int kindn, ret = -ENOSYS;
240 const u8 *kindm;
241
242 map->type = map->ctag = 0;
243 map->next = 1 << page->shift;
244
245 if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
246 ro = !!args->v0.ro;
247 priv = !!args->v0.priv;
248 kind = args->v0.kind & 0x7f;
249 comp = args->v0.comp & 0x03;
250 } else
251 if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) {
252 ro = 0;
253 priv = 0;
254 kind = 0x00;
255 comp = 0;
256 } else {
257 VMM_DEBUG(vmm, "args");
258 return ret;
259 }
260
261 switch (nvkm_memory_target(memory)) {
262 case NVKM_MEM_TARGET_VRAM:
263 if (ram->stolen) {
264 map->type |= ram->stolen;
265 aper = 3;
266 } else {
267 aper = 0;
268 }
269 break;
270 case NVKM_MEM_TARGET_HOST:
271 aper = 2;
272 break;
273 case NVKM_MEM_TARGET_NCOH:
274 aper = 3;
275 break;
276 default:
277 WARN_ON(1);
278 return -EINVAL;
279 }
280
281 kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
282 if (kind >= kindn || kindm[kind] == 0x7f) {
283 VMM_DEBUG(vmm, "kind %02x", kind);
284 return -EINVAL;
285 }
286
287 if (map->mem && map->mem->type != kindm[kind]) {
288 VMM_DEBUG(vmm, "kind %02x bankswz: %d %d", kind,
289 kindm[kind], map->mem->type);
290 return -EINVAL;
291 }
292
293 if (comp) {
294 u32 tags = (nvkm_memory_size(memory) >> 16) * comp;
295 if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) {
296 VMM_DEBUG(vmm, "comp %d %02x", aper, page->type);
297 return -EINVAL;
298 }
299
300 ret = nvkm_memory_tags_get(memory, device, tags, NULL,
301 &map->tags);
302 if (ret) {
303 VMM_DEBUG(vmm, "comp %d", ret);
304 return ret;
305 }
306
307 if (map->tags->mn) {
308 u32 tags = map->tags->mn->offset + (map->offset >> 16);
309 map->ctag |= (u64)comp << 49;
310 map->type |= (u64)comp << 47;
311 map->type |= (u64)tags << 49;
312 map->next |= map->ctag;
313 }
314 }
315
316 map->type |= BIT(0); /* Valid. */
317 map->type |= (u64)ro << 3;
318 map->type |= (u64)aper << 4;
319 map->type |= (u64)priv << 6;
320 map->type |= (u64)kind << 40;
321 return 0;
322}
323
324static void
325nv50_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
326{
327 struct nvkm_vmm_join *join;
328
329 list_for_each_entry(join, &vmm->join, head) {
330 if (join->inst == inst) {
331 list_del(&join->head);
332 kfree(join);
333 break;
334 }
335 }
336}
337
338static int
339nv50_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst)
340{
341 const u32 pd_offset = vmm->mmu->func->vmm.pd_offset;
342 struct nvkm_vmm_join *join;
343 int ret = 0;
344 u64 data;
345 u32 pdei;
346
347 if (!(join = kmalloc(sizeof(*join), GFP_KERNEL)))
348 return -ENOMEM;
349 join->inst = inst;
350 list_add_tail(&join->head, &vmm->join);
351
352 nvkm_kmap(join->inst);
353 for (pdei = vmm->start >> 29; pdei <= (vmm->limit - 1) >> 29; pdei++) {
354 if (!nv50_vmm_pde(vmm, vmm->pd->pde[pdei], &data)) {
355 ret = -EINVAL;
356 break;
357 }
358 nvkm_wo64(join->inst, pd_offset + (pdei * 8), data);
359 }
360 nvkm_done(join->inst);
361 return ret;
362}
363
364static const struct nvkm_vmm_func
365nv50_vmm = {
366 .join = nv50_vmm_join,
367 .part = nv50_vmm_part,
368 .valid = nv50_vmm_valid,
369 .flush = nv50_vmm_flush,
370 .page_block = 1 << 29,
371 .page = {
372 { 16, &nv50_vmm_desc_16[0], NVKM_VMM_PAGE_xVxC },
373 { 12, &nv50_vmm_desc_12[0], NVKM_VMM_PAGE_xVHx },
374 {}
375 }
376};
377
378int
379nv50_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc,
380 struct lock_class_key *key, const char *name,
381 struct nvkm_vmm **pvmm)
382{
383 return nv04_vmm_new_(&nv50_vmm, mmu, 0, addr, size,
384 argv, argc, key, name, pvmm);
385}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index a4cb82495cee..b1b1f3626b96 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -87,7 +87,7 @@ nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend)
87 if (pci->irq >= 0) { 87 if (pci->irq >= 0) {
88 free_irq(pci->irq, pci); 88 free_irq(pci->irq, pci);
89 pci->irq = -1; 89 pci->irq = -1;
90 }; 90 }
91 91
92 if (pci->agp.bridge) 92 if (pci->agp.bridge)
93 nvkm_agp_fini(pci); 93 nvkm_agp_fini(pci);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
index 73ca1203281d..5e91b3f90065 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
@@ -39,7 +39,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
39{ 39{
40 struct gm200_secboot *gsb = gm200_secboot(sb); 40 struct gm200_secboot *gsb = gm200_secboot(sb);
41 struct nvkm_subdev *subdev = &gsb->base.subdev; 41 struct nvkm_subdev *subdev = &gsb->base.subdev;
42 struct nvkm_vma vma; 42 struct nvkm_vma *vma = NULL;
43 u32 start_address; 43 u32 start_address;
44 int ret; 44 int ret;
45 45
@@ -48,12 +48,16 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
48 return ret; 48 return ret;
49 49
50 /* Map the HS firmware so the HS bootloader can see it */ 50 /* Map the HS firmware so the HS bootloader can see it */
51 ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma); 51 ret = nvkm_vmm_get(gsb->vmm, 12, blob->size, &vma);
52 if (ret) { 52 if (ret) {
53 nvkm_falcon_put(falcon, subdev); 53 nvkm_falcon_put(falcon, subdev);
54 return ret; 54 return ret;
55 } 55 }
56 56
57 ret = nvkm_memory_map(blob, 0, gsb->vmm, vma, NULL, 0);
58 if (ret)
59 goto end;
60
57 /* Reset and set the falcon up */ 61 /* Reset and set the falcon up */
58 ret = nvkm_falcon_reset(falcon); 62 ret = nvkm_falcon_reset(falcon);
59 if (ret) 63 if (ret)
@@ -61,7 +65,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob,
61 nvkm_falcon_bind_context(falcon, gsb->inst); 65 nvkm_falcon_bind_context(falcon, gsb->inst);
62 66
63 /* Load the HS bootloader into the falcon's IMEM/DMEM */ 67 /* Load the HS bootloader into the falcon's IMEM/DMEM */
64 ret = sb->acr->func->load(sb->acr, falcon, blob, vma.offset); 68 ret = sb->acr->func->load(sb->acr, falcon, blob, vma->addr);
65 if (ret < 0) 69 if (ret < 0)
66 goto end; 70 goto end;
67 71
@@ -91,7 +95,7 @@ end:
91 nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true); 95 nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true);
92 96
93 /* We don't need the ACR firmware anymore */ 97 /* We don't need the ACR firmware anymore */
94 nvkm_gpuobj_unmap(&vma); 98 nvkm_vmm_put(gsb->vmm, &vma);
95 nvkm_falcon_put(falcon, subdev); 99 nvkm_falcon_put(falcon, subdev);
96 100
97 return ret; 101 return ret;
@@ -102,37 +106,26 @@ gm200_secboot_oneinit(struct nvkm_secboot *sb)
102{ 106{
103 struct gm200_secboot *gsb = gm200_secboot(sb); 107 struct gm200_secboot *gsb = gm200_secboot(sb);
104 struct nvkm_device *device = sb->subdev.device; 108 struct nvkm_device *device = sb->subdev.device;
105 struct nvkm_vm *vm;
106 const u64 vm_area_len = 600 * 1024;
107 int ret; 109 int ret;
108 110
109 /* Allocate instance block and VM */ 111 /* Allocate instance block and VM */
110 ret = nvkm_gpuobj_new(device, 0x1000, 0, true, NULL, &gsb->inst); 112 ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true,
113 &gsb->inst);
111 if (ret) 114 if (ret)
112 return ret; 115 return ret;
113 116
114 ret = nvkm_gpuobj_new(device, 0x8000, 0, true, NULL, &gsb->pgd); 117 ret = nvkm_vmm_new(device, 0, 600 * 1024, NULL, 0, NULL, "acr",
118 &gsb->vmm);
115 if (ret) 119 if (ret)
116 return ret; 120 return ret;
117 121
118 ret = nvkm_vm_new(device, 0, vm_area_len, 0, NULL, &vm); 122 atomic_inc(&gsb->vmm->engref[NVKM_SUBDEV_PMU]);
119 if (ret) 123 gsb->vmm->debug = gsb->base.subdev.debug;
120 return ret;
121
122 atomic_inc(&vm->engref[NVKM_SUBDEV_PMU]);
123 124
124 ret = nvkm_vm_ref(vm, &gsb->vm, gsb->pgd); 125 ret = nvkm_vmm_join(gsb->vmm, gsb->inst);
125 nvkm_vm_ref(NULL, &vm, NULL);
126 if (ret) 126 if (ret)
127 return ret; 127 return ret;
128 128
129 nvkm_kmap(gsb->inst);
130 nvkm_wo32(gsb->inst, 0x200, lower_32_bits(gsb->pgd->addr));
131 nvkm_wo32(gsb->inst, 0x204, upper_32_bits(gsb->pgd->addr));
132 nvkm_wo32(gsb->inst, 0x208, lower_32_bits(vm_area_len - 1));
133 nvkm_wo32(gsb->inst, 0x20c, upper_32_bits(vm_area_len - 1));
134 nvkm_done(gsb->inst);
135
136 if (sb->acr->func->oneinit) { 129 if (sb->acr->func->oneinit) {
137 ret = sb->acr->func->oneinit(sb->acr, sb); 130 ret = sb->acr->func->oneinit(sb->acr, sb);
138 if (ret) 131 if (ret)
@@ -160,9 +153,9 @@ gm200_secboot_dtor(struct nvkm_secboot *sb)
160 153
161 sb->acr->func->dtor(sb->acr); 154 sb->acr->func->dtor(sb->acr);
162 155
163 nvkm_vm_ref(NULL, &gsb->vm, gsb->pgd); 156 nvkm_vmm_part(gsb->vmm, gsb->inst);
164 nvkm_gpuobj_del(&gsb->pgd); 157 nvkm_vmm_unref(&gsb->vmm);
165 nvkm_gpuobj_del(&gsb->inst); 158 nvkm_memory_unref(&gsb->inst);
166 159
167 return gsb; 160 return gsb;
168} 161}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h
index c8ab3d76bdef..62c5e162099a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h
@@ -29,9 +29,8 @@ struct gm200_secboot {
29 struct nvkm_secboot base; 29 struct nvkm_secboot base;
30 30
31 /* Instance block & address space used for HS FW execution */ 31 /* Instance block & address space used for HS FW execution */
32 struct nvkm_gpuobj *inst; 32 struct nvkm_memory *inst;
33 struct nvkm_gpuobj *pgd; 33 struct nvkm_vmm *vmm;
34 struct nvkm_vm *vm;
35}; 34};
36#define gm200_secboot(sb) container_of(sb, struct gm200_secboot, base) 35#define gm200_secboot(sb) container_of(sb, struct gm200_secboot, base)
37 36
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
index ee989210725e..6f10b098676c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
@@ -183,7 +183,7 @@ acr_ls_sec2_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb)
183 break; 183 break;
184 ); 184 );
185 if (reg & BIT(4)) { 185 if (reg & BIT(4)) {
186 nvkm_debug(subdev, "applying workaround for start bug..."); 186 nvkm_debug(subdev, "applying workaround for start bug...\n");
187 nvkm_falcon_start(sb->boot_falcon); 187 nvkm_falcon_start(sb->boot_falcon);
188 nvkm_msec(subdev->device, 1, 188 nvkm_msec(subdev->device, 1,
189 if ((reg = nvkm_rd32(subdev->device, 189 if ((reg = nvkm_rd32(subdev->device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h
index 885e919a8720..d9091f029506 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h
@@ -25,6 +25,7 @@
25 25
26#include <subdev/secboot.h> 26#include <subdev/secboot.h>
27#include <subdev/mmu.h> 27#include <subdev/mmu.h>
28struct nvkm_gpuobj;
28 29
29struct nvkm_secboot_func { 30struct nvkm_secboot_func {
30 int (*oneinit)(struct nvkm_secboot *); 31 int (*oneinit)(struct nvkm_secboot *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
index 2bafcc1d1818..7ba56b12badd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild
@@ -12,3 +12,4 @@ nvkm-y += nvkm/subdev/therm/gt215.o
12nvkm-y += nvkm/subdev/therm/gf119.o 12nvkm-y += nvkm/subdev/therm/gf119.o
13nvkm-y += nvkm/subdev/therm/gm107.o 13nvkm-y += nvkm/subdev/therm/gm107.o
14nvkm-y += nvkm/subdev/therm/gm200.o 14nvkm-y += nvkm/subdev/therm/gm200.o
15nvkm-y += nvkm/subdev/therm/gp100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
index 952a7cb0a59a..f27fc6d0d4c6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
@@ -341,7 +341,8 @@ nvkm_therm_init(struct nvkm_subdev *subdev)
341{ 341{
342 struct nvkm_therm *therm = nvkm_therm(subdev); 342 struct nvkm_therm *therm = nvkm_therm(subdev);
343 343
344 therm->func->init(therm); 344 if (therm->func->init)
345 therm->func->init(therm);
345 346
346 if (therm->suspend >= 0) { 347 if (therm->suspend >= 0) {
347 /* restore the pwm value only when on manual or auto mode */ 348 /* restore the pwm value only when on manual or auto mode */
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c
new file mode 100644
index 000000000000..9f0dea3f61dc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c
@@ -0,0 +1,56 @@
1/*
2 * Copyright 2017 Rhys Kidd
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Rhys Kidd
23 */
24#include "priv.h"
25
26static int
27gp100_temp_get(struct nvkm_therm *therm)
28{
29 struct nvkm_device *device = therm->subdev.device;
30 struct nvkm_subdev *subdev = &therm->subdev;
31 u32 tsensor = nvkm_rd32(device, 0x020460);
32 u32 inttemp = (tsensor & 0x0001fff8);
33
34 /* device SHADOWed */
35 if (tsensor & 0x40000000)
36 nvkm_trace(subdev, "reading temperature from SHADOWed sensor\n");
37
38 /* device valid */
39 if (tsensor & 0x20000000)
40 return (inttemp >> 8);
41 else
42 return -ENODEV;
43}
44
45static const struct nvkm_therm_func
46gp100_therm = {
47 .temp_get = gp100_temp_get,
48 .program_alarms = nvkm_therm_program_alarms_polling,
49};
50
51int
52gp100_therm_new(struct nvkm_device *device, int index,
53 struct nvkm_therm **ptherm)
54{
55 return nvkm_therm_new_(&gp100_therm, device, index, ptherm);
56}