diff options
| author | Dave Airlie <airlied@redhat.com> | 2017-11-02 00:00:35 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2017-11-02 00:00:53 -0400 |
| commit | 2ef7a95fe537c0e2ee039179ecab27e6d63fa1e1 (patch) | |
| tree | 9ef67d24ff8e9b5242eb545237e9dddcd3463a7c /drivers/gpu | |
| parent | 7a88cbd8d65d622c00bd76ba4ae1d893b292c91c (diff) | |
| parent | 46bda4f4af5d061ce07148e833ff4deb50737536 (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')
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 |
| 31 | nouveau-y += nouveau_bo.o | 31 | nouveau-y += nouveau_bo.o |
| 32 | nouveau-y += nouveau_gem.o | 32 | nouveau-y += nouveau_gem.o |
| 33 | nouveau-y += nouveau_mem.o | ||
| 33 | nouveau-y += nouveau_prime.o | 34 | nouveau-y += nouveau_prime.o |
| 34 | nouveau-y += nouveau_sgdma.o | 35 | nouveau-y += nouveau_sgdma.o |
| 35 | nouveau-y += nouveau_ttm.o | 36 | nouveau-y += nouveau_ttm.o |
| 37 | nouveau-y += nouveau_vmm.o | ||
| 36 | 38 | ||
| 37 | # DRM - modesetting | 39 | # DRM - modesetting |
| 38 | nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o | 40 | nouveau-$(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 | ||
| 59 | config 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 | |||
| 59 | config DRM_NOUVEAU_BACKLIGHT | 66 | config 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__ | ||
| 3 | struct 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 | |||
| 15 | struct nvif_mmu_heap_v0 { | ||
| 16 | __u8 version; | ||
| 17 | __u8 index; | ||
| 18 | __u8 pad02[6]; | ||
| 19 | __u64 size; | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct 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 | |||
| 36 | struct 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__ | ||
| 3 | struct 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 | |||
| 13 | struct nvif_mem_ram_vn { | ||
| 14 | }; | ||
| 15 | |||
| 16 | struct 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 | |||
| 5 | struct nv04_mem_vn { | ||
| 6 | /* nvkm_mem_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct 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__ | ||
| 3 | struct 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 | |||
| 18 | struct 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 | |||
| 29 | struct 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 | |||
| 43 | struct nvif_vmm_put_v0 { | ||
| 44 | __u8 version; | ||
| 45 | __u8 pad01[7]; | ||
| 46 | __u64 addr; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct 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 | |||
| 59 | struct 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 | |||
| 5 | struct nv04_vmm_vn { | ||
| 6 | /* nvif_vmm_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct 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 | |||
| 5 | struct nv50_mem_vn { | ||
| 6 | /* nvif_mem_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct nv50_mem_v0 { | ||
| 10 | /* nvif_mem_vX ... */ | ||
| 11 | __u8 version; | ||
| 12 | __u8 bankswz; | ||
| 13 | __u8 contig; | ||
| 14 | }; | ||
| 15 | |||
| 16 | struct nv50_mem_map_vn { | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct 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 | |||
| 5 | struct nv50_vmm_vn { | ||
| 6 | /* nvif_vmm_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct nv50_vmm_map_vn { | ||
| 10 | /* nvif_vmm_map_vX ... */ | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct 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 | |||
| 5 | struct gf100_mem_vn { | ||
| 6 | /* nvif_mem_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct gf100_mem_v0 { | ||
| 10 | /* nvif_mem_vX ... */ | ||
| 11 | __u8 version; | ||
| 12 | __u8 contig; | ||
| 13 | }; | ||
| 14 | |||
| 15 | struct gf100_mem_map_vn { | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct 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 | |||
| 5 | struct gf100_vmm_vn { | ||
| 6 | /* nvif_vmm_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct gf100_vmm_map_vn { | ||
| 10 | /* nvif_vmm_map_vX ... */ | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct 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 | |||
| 5 | struct gm200_vmm_vn { | ||
| 6 | /* nvif_vmm_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct gm200_vmm_v0 { | ||
| 10 | /* nvif_vmm_vX ... */ | ||
| 11 | __u8 version; | ||
| 12 | __u8 bigpage; | ||
| 13 | }; | ||
| 14 | |||
| 15 | struct gm200_vmm_map_vn { | ||
| 16 | /* nvif_vmm_map_vX ... */ | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct 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 | |||
| 5 | struct gp100_vmm_vn { | ||
| 6 | /* nvif_vmm_vX ... */ | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct gp100_vmm_map_vn { | ||
| 10 | /* nvif_vmm_map_vX ... */ | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct 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 | ||
| 6 | struct nvif_ioctl_v0 { | 6 | struct nvif_ioctl_v0 { |
| 7 | __u8 version; | 7 | __u8 version; |
| @@ -83,9 +83,13 @@ struct nvif_ioctl_wr_v0 { | |||
| 83 | struct nvif_ioctl_map_v0 { | 83 | struct 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 | ||
| 91 | struct nvif_ioctl_unmap { | 95 | struct 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 | |||
| 5 | struct nvif_mem { | ||
| 6 | struct nvif_object object; | ||
| 7 | u8 type; | ||
| 8 | u8 page; | ||
| 9 | u64 addr; | ||
| 10 | u64 size; | ||
| 11 | }; | ||
| 12 | |||
| 13 | int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page, | ||
| 14 | u64 size, void *argv, u32 argc, struct nvif_mem *); | ||
| 15 | int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page, | ||
| 16 | u64 size, void *argv, u32 argc, struct nvif_mem *); | ||
| 17 | void 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 | |||
| 5 | struct 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 | |||
| 32 | int nvif_mmu_init(struct nvif_object *, s32 oclass, struct nvif_mmu *); | ||
| 33 | void nvif_mmu_fini(struct nvif_mmu *); | ||
| 34 | |||
| 35 | static inline bool | ||
| 36 | nvif_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 | |||
| 46 | static inline int | ||
| 47 | nvif_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 **); | |||
| 29 | u32 nvif_object_rd(struct nvif_object *, int, u64); | 29 | u32 nvif_object_rd(struct nvif_object *, int, u64); |
| 30 | void nvif_object_wr(struct nvif_object *, int, u64, u32); | 30 | void nvif_object_wr(struct nvif_object *, int, u64, u32); |
| 31 | int nvif_object_mthd(struct nvif_object *, u32, void *, u32); | 31 | int nvif_object_mthd(struct nvif_object *, u32, void *, u32); |
| 32 | int nvif_object_map(struct nvif_object *); | 32 | int nvif_object_map_handle(struct nvif_object *, void *, u32, |
| 33 | u64 *handle, u64 *length); | ||
| 34 | void nvif_object_unmap_handle(struct nvif_object *); | ||
| 35 | int nvif_object_map(struct nvif_object *, void *, u32); | ||
| 33 | void nvif_object_unmap(struct nvif_object *); | 36 | void 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> | ||
| 4 | struct nvif_mem; | ||
| 5 | struct nvif_mmu; | ||
| 6 | |||
| 7 | enum nvif_vmm_get { | ||
| 8 | ADDR, | ||
| 9 | PTES, | ||
| 10 | LAZY | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct nvif_vma { | ||
| 14 | u64 addr; | ||
| 15 | u64 size; | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct 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 | |||
| 33 | int nvif_vmm_init(struct nvif_mmu *, s32 oclass, u64 addr, u64 size, | ||
| 34 | void *argv, u32 argc, struct nvif_vmm *); | ||
| 35 | void nvif_vmm_fini(struct nvif_vmm *); | ||
| 36 | int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse, | ||
| 37 | u8 page, u8 align, u64 size, struct nvif_vma *); | ||
| 38 | void nvif_vmm_put(struct nvif_vmm *, struct nvif_vma *); | ||
| 39 | int nvif_vmm_map(struct nvif_vmm *, u64 addr, u64 size, void *argv, u32 argc, | ||
| 40 | struct nvif_mem *, u64 offset); | ||
| 41 | int 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 | ||
| 22 | int nvkm_client_new(const char *name, u64 device, const char *cfg, | 23 | int 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 | ||
| 6 | enum nvkm_devidx { | 6 | enum 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 | ||
| 16 | struct nvkm_engine_func { | 16 | struct 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> |
| 6 | struct nvkm_vma; | ||
| 7 | struct 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 | ||
| 12 | struct nvkm_gpuobj { | 9 | struct 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 | ||
| 33 | int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, | 34 | int 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 **); |
| 35 | void nvkm_gpuobj_del(struct nvkm_gpuobj **); | 36 | void nvkm_gpuobj_del(struct nvkm_gpuobj **); |
| 36 | int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); | 37 | int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); |
| 37 | int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, | ||
| 38 | struct nvkm_vma *); | ||
| 39 | void nvkm_gpuobj_unmap(struct nvkm_vma *); | ||
| 40 | void nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src, | 38 | void nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src, |
| 41 | u32 length); | 39 | u32 length); |
| 42 | void nvkm_gpuobj_memcpy_from(void *dst, struct nvkm_gpuobj *src, u32 srcoffset, | 40 | void 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> |
| 4 | struct nvkm_device; | 4 | struct nvkm_device; |
| 5 | struct nvkm_vma; | 5 | struct nvkm_vma; |
| 6 | struct nvkm_vm; | 6 | struct nvkm_vmm; |
| 7 | |||
| 8 | struct nvkm_tags { | ||
| 9 | struct nvkm_mm_node *mn; | ||
| 10 | refcount_t refcount; | ||
| 11 | }; | ||
| 7 | 12 | ||
| 8 | enum nvkm_memory_target { | 13 | enum 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 | ||
| 15 | struct nvkm_memory { | 20 | struct 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 | ||
| 19 | struct nvkm_memory_func { | 27 | struct 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 | |||
| 40 | struct 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 | ||
| 32 | void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *); | 45 | void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *); |
| 33 | int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target, | 46 | int 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 **); |
| 35 | void nvkm_memory_del(struct nvkm_memory **); | 48 | struct nvkm_memory *nvkm_memory_ref(struct nvkm_memory *); |
| 49 | void nvkm_memory_unref(struct nvkm_memory **); | ||
| 50 | int nvkm_memory_tags_get(struct nvkm_memory *, struct nvkm_device *, u32 tags, | ||
| 51 | void (*clear)(struct nvkm_device *, u32, u32), | ||
| 52 | struct nvkm_tags **); | ||
| 53 | void 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 | ||
| 33 | int nvkm_mm_init(struct nvkm_mm *, u32 offset, u32 length, u32 block); | 33 | int nvkm_mm_init(struct nvkm_mm *, u8 heap, u32 offset, u32 length, u32 block); |
| 34 | int nvkm_mm_fini(struct nvkm_mm *); | 34 | int nvkm_mm_fini(struct nvkm_mm *); |
| 35 | int nvkm_mm_head(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, | 35 | int 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, | |||
| 39 | void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **); | 39 | void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **); |
| 40 | void nvkm_mm_dump(struct nvkm_mm *, const char *); | 40 | void nvkm_mm_dump(struct nvkm_mm *, const char *); |
| 41 | 41 | ||
| 42 | static inline u32 | ||
| 43 | nvkm_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 | |||
| 42 | static inline bool | 54 | static inline bool |
| 43 | nvkm_mm_contiguous(struct nvkm_mm_node *node) | 55 | nvkm_mm_contiguous(struct nvkm_mm_node *node) |
| 44 | { | 56 | { |
| 45 | return !node->next; | 57 | return !node->next; |
| 46 | } | 58 | } |
| 59 | |||
| 60 | static inline u32 | ||
| 61 | nvkm_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 | |||
| 68 | static inline u32 | ||
| 69 | nvkm_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> | ||
| 5 | struct nvkm_event; | 4 | struct nvkm_event; |
| 6 | struct nvkm_gpuobj; | 5 | struct nvkm_gpuobj; |
| 7 | struct nvkm_oclass; | ||
| 8 | 6 | ||
| 9 | struct nvkm_object { | 7 | struct 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 | ||
| 22 | enum nvkm_object_map { | ||
| 23 | NVKM_OBJECT_MAP_IO, | ||
| 24 | NVKM_OBJECT_MAP_VA | ||
| 25 | }; | ||
| 26 | |||
| 24 | struct nvkm_object_func { | 27 | struct 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 *); | |||
| 52 | int nvkm_object_fini(struct nvkm_object *, bool suspend); | 57 | int nvkm_object_fini(struct nvkm_object *, bool suspend); |
| 53 | int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); | 58 | int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); |
| 54 | int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); | 59 | int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); |
| 55 | int nvkm_object_map(struct nvkm_object *, u64 *addr, u32 *size); | 60 | int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc, |
| 61 | enum nvkm_object_map *, u64 *addr, u64 *size); | ||
| 62 | int nvkm_object_unmap(struct nvkm_object *); | ||
| 56 | int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); | 63 | int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); |
| 57 | int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); | 64 | int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); |
| 58 | int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); | 65 | int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); |
| @@ -66,28 +73,4 @@ bool nvkm_object_insert(struct nvkm_object *); | |||
| 66 | void nvkm_object_remove(struct nvkm_object *); | 73 | void nvkm_object_remove(struct nvkm_object *); |
| 67 | struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object, | 74 | struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object, |
| 68 | const struct nvkm_object_func *); | 75 | const struct nvkm_object_func *); |
| 69 | |||
| 70 | struct 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 | |||
| 79 | struct 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> | ||
| 5 | struct nvkm_oclass; | ||
| 6 | struct nvkm_object; | ||
| 7 | |||
| 8 | struct 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 | |||
| 17 | struct 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> |
| 4 | struct nvkm_object; | ||
| 4 | 5 | ||
| 5 | struct nvkm_ramht_data { | 6 | struct 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> | ||
| 4 | struct nvkm_client; | 5 | struct nvkm_client; |
| 5 | 6 | ||
| 6 | struct nvkm_dmaobj { | 7 | struct 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> |
| 5 | struct nvkm_fifo_chan; | 5 | struct nvkm_fifo_chan; |
| 6 | struct nvkm_gpuobj; | ||
| 6 | 7 | ||
| 7 | enum nvkm_falcon_dmaidx { | 8 | enum 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); |
| 113 | void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); | 114 | void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); |
| 114 | void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); | 115 | void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); |
| 115 | void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *); | 116 | void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *); |
| 116 | void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); | 117 | void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); |
| 117 | void nvkm_falcon_start(struct nvkm_falcon *); | 118 | void nvkm_falcon_start(struct nvkm_falcon *); |
| 118 | int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); | 119 | int 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 | ||
| 17 | struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *); | ||
| 18 | void nvkm_bar_bar2_init(struct nvkm_device *); | ||
| 19 | void nvkm_bar_bar2_fini(struct nvkm_device *); | ||
| 20 | struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *); | ||
| 16 | void nvkm_bar_flush(struct nvkm_bar *); | 21 | void nvkm_bar_flush(struct nvkm_bar *); |
| 17 | struct nvkm_vm *nvkm_bar_kmap(struct nvkm_bar *); | ||
| 18 | int nvkm_bar_umap(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); | ||
| 19 | 22 | ||
| 20 | int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **); | 23 | int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **); |
| 21 | int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **); | 24 | int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **); |
| 22 | int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); | 25 | int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); |
| 23 | int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); | 26 | int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); |
| 27 | int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **); | ||
| 28 | int 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 | ||
| 24 | struct 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 | |||
| 40 | struct nvkm_fb_tile { | 23 | struct 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 | ||
| 65 | bool nvkm_fb_memtype_valid(struct nvkm_fb *, u32 memtype); | ||
| 66 | void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size, | 49 | void 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 *); |
| 68 | void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *); | 51 | void 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 | ||
| 136 | int | ||
| 137 | nvkm_ram_get(struct nvkm_device *, u8 heap, u8 type, u8 page, u64 size, | ||
| 138 | bool contig, bool back, struct nvkm_memory **); | ||
| 139 | |||
| 150 | struct nvkm_ram_func { | 140 | struct 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 | |||
| 169 | extern 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 | ||
| 26 | int nvkm_ltc_tags_alloc(struct nvkm_ltc *, u32 count, struct nvkm_mm_node **); | 25 | void nvkm_ltc_tags_clear(struct nvkm_device *, u32 first, u32 count); |
| 27 | void nvkm_ltc_tags_free(struct nvkm_ltc *, struct nvkm_mm_node **); | ||
| 28 | void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count); | ||
| 29 | 26 | ||
| 30 | int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); | 27 | int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); |
| 31 | int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); | 28 | int 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> | ||
| 5 | struct nvkm_device; | ||
| 6 | struct nvkm_mem; | ||
| 7 | |||
| 8 | struct nvkm_vm_pgt { | ||
| 9 | struct nvkm_memory *mem[2]; | ||
| 10 | u32 refcount[2]; | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct nvkm_vm_pgd { | ||
| 14 | struct list_head head; | ||
| 15 | struct nvkm_gpuobj *obj; | ||
| 16 | }; | ||
| 17 | 4 | ||
| 18 | struct nvkm_vma { | 5 | struct 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 | ||
| 27 | struct nvkm_vm { | 23 | struct 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 | ||
| 42 | int nvkm_vm_new(struct nvkm_device *, u64 offset, u64 length, u64 mm_offset, | 48 | int 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 **); |
| 44 | int nvkm_vm_ref(struct nvkm_vm *, struct nvkm_vm **, struct nvkm_gpuobj *pgd); | 50 | struct nvkm_vmm *nvkm_vmm_ref(struct nvkm_vmm *); |
| 45 | int nvkm_vm_boot(struct nvkm_vm *, u64 size); | 51 | void nvkm_vmm_unref(struct nvkm_vmm **); |
| 46 | int nvkm_vm_get(struct nvkm_vm *, u64 size, u32 page_shift, u32 access, | 52 | int nvkm_vmm_boot(struct nvkm_vmm *); |
| 47 | struct nvkm_vma *); | 53 | int nvkm_vmm_join(struct nvkm_vmm *, struct nvkm_memory *inst); |
| 48 | void nvkm_vm_put(struct nvkm_vma *); | 54 | void nvkm_vmm_part(struct nvkm_vmm *, struct nvkm_memory *inst); |
| 49 | void nvkm_vm_map(struct nvkm_vma *, struct nvkm_mem *); | 55 | int nvkm_vmm_get(struct nvkm_vmm *, u8 page, u64 size, struct nvkm_vma **); |
| 50 | void nvkm_vm_map_at(struct nvkm_vma *, u64 offset, struct nvkm_mem *); | 56 | void nvkm_vmm_put(struct nvkm_vmm *, struct nvkm_vma **); |
| 51 | void nvkm_vm_unmap(struct nvkm_vma *); | 57 | |
| 52 | void nvkm_vm_unmap_at(struct nvkm_vma *, u64 offset, u64 length); | 58 | struct 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 | |||
| 75 | int nvkm_vmm_map(struct nvkm_vmm *, struct nvkm_vma *, void *argv, u32 argc, | ||
| 76 | struct nvkm_vmm_map *); | ||
| 77 | void nvkm_vmm_unmap(struct nvkm_vmm *, struct nvkm_vma *); | ||
| 78 | |||
| 79 | struct nvkm_memory *nvkm_umem_search(struct nvkm_client *, u64); | ||
| 80 | struct nvkm_vmm *nvkm_uvmm_search(struct nvkm_client *, u64 handle); | ||
| 53 | 81 | ||
| 54 | struct nvkm_mmu { | 82 | struct 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 | ||
| 63 | int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | 118 | int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); |
| 64 | int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | 119 | int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); |
| 65 | int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | 120 | int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); |
| 66 | int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | 121 | int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); |
| 122 | int g84_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 67 | int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | 123 | int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); |
| 124 | int gk104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 125 | int gk20a_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 126 | int gm200_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 127 | int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 128 | int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); | ||
| 129 | int 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 **); | |||
| 97 | int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); | 97 | int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); |
| 98 | int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); | 98 | int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); |
| 99 | int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **); | 99 | int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **); |
| 100 | int 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 | ||
| 38 | static struct nouveau_abi16 * | 39 | static struct nouveau_abi16 * |
| 39 | nouveau_abi16(struct drm_file *file_priv) | 40 | nouveau_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); |
| 344 | done: | 348 | done: |
| 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(®->fence); | 60 | nouveau_fence_unref(®->fence); |
| @@ -97,7 +102,7 @@ nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, | |||
| 97 | 102 | ||
| 98 | static struct nouveau_drm_tile * | 103 | static struct nouveau_drm_tile * |
| 99 | nv10_bo_set_tiling(struct drm_device *dev, u32 addr, | 104 | nv10_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 | ||
| 377 | out: | 440 | out: |
| 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 | |||
| 446 | nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) | 509 | nouveau_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 | |||
| 466 | nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) | 529 | nouveau_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 | |||
| 659 | nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 723 | nve0_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 | |||
| 691 | nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 755 | nvc0_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 | |||
| 729 | nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 793 | nvc0_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 | |||
| 768 | nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 832 | nva3_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 | |||
| 806 | nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 870 | nv98_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 | |||
| 824 | nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 888 | nv84_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 | |||
| 858 | nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 922 | nv50_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 | |||
| 1000 | nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, | 1064 | nouveau_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]); | ||
| 1087 | done: | ||
| 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 | |||
| 1200 | nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, | 1270 | nouveau_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) | |||
| 1385 | static void | 1476 | static void |
| 1386 | nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) | 1477 | nouveau_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 | ||
| 1397 | static int | 1497 | static 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 | |||
| 1580 | struct nvkm_vma * | ||
| 1581 | nouveau_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 | |||
| 1592 | int | ||
| 1593 | nouveau_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 | |||
| 1614 | void | ||
| 1615 | nouveau_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, | |||
| 89 | void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo); | 93 | void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo); |
| 90 | void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo); | 94 | void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo); |
| 91 | 95 | ||
| 92 | struct nvkm_vma * | ||
| 93 | nouveau_bo_vma_find(struct nouveau_bo *, struct nvkm_vm *); | ||
| 94 | |||
| 95 | int nouveau_bo_vma_add(struct nouveau_bo *, struct nvkm_vm *, | ||
| 96 | struct nvkm_vma *); | ||
| 97 | void 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? */ |
| 100 | static inline void __iomem * | 97 | static inline void __iomem * |
| 101 | nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) | 98 | nvbo_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 | ||
| 44 | MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); | 45 | MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); |
| 45 | int nouveau_vram_pushbuf; | 46 | int 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 | |||
| 203 | nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, | 216 | nouveau_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 | ||
| 8 | struct nouveau_framebuffer { | 5 | struct 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 | ||
| 30 | void | 31 | void |
| 31 | OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) | 32 | OUT_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 | ||
| 81 | void | 82 | void |
| @@ -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 | ||
| 146 | static inline void | 146 | static 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 | ||
| 114 | static inline bool | ||
| 115 | nouveau_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 | |||
| 126 | static void | ||
| 127 | nouveau_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 | |||
| 140 | static void | ||
| 141 | nouveau_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 | |||
| 147 | void | ||
| 148 | nouveau_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 | |||
| 160 | static void | ||
| 161 | nouveau_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 | |||
| 114 | static void | 167 | static void |
| 115 | nouveau_cli_fini(struct nouveau_cli *cli) | 168 | nouveau_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 | ||
| 123 | static int | 180 | static int |
| 124 | nouveau_cli_init(struct nouveau_drm *drm, const char *sname, | 181 | nouveau_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; | ||
| 157 | done: | 275 | done: |
| 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); |
| 517 | fail_ttm: | 624 | fail_ttm: |
| 518 | nouveau_vga_fini(drm); | 625 | nouveau_vga_fini(drm); |
| 519 | fail_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 | ||
| 65 | struct nouveau_drm_tile { | 68 | struct nouveau_drm_tile { |
| 66 | struct nouveau_fence *fence; | 69 | struct nouveau_fence *fence; |
| @@ -86,19 +89,37 @@ enum nouveau_drm_handle { | |||
| 86 | 89 | ||
| 87 | struct nouveau_cli { | 90 | struct 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 | ||
| 111 | struct 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 | |||
| 120 | void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, | ||
| 121 | struct nouveau_cli_work *); | ||
| 122 | |||
| 102 | static inline struct nouveau_cli * | 123 | static inline struct nouveau_cli * |
| 103 | nouveau_cli(struct drm_file *fpriv) | 124 | nouveau_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 | ||
| 111 | struct nouveau_drm { | 132 | struct 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 | ||
| 403 | out_unlock: | 404 | out_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); |
| 407 | out_unpin: | 408 | out_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 | ||
| 202 | struct nouveau_fence_work { | ||
| 203 | struct work_struct work; | ||
| 204 | struct dma_fence_cb cb; | ||
| 205 | void (*func)(void *); | ||
| 206 | void *data; | ||
| 207 | }; | ||
| 208 | |||
| 209 | static void | ||
| 210 | nouveau_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 | |||
| 217 | static 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 | |||
| 224 | void | ||
| 225 | nouveau_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 | |||
| 252 | err_free: | ||
| 253 | kfree(work); | ||
| 254 | err: | ||
| 255 | func(data); | ||
| 256 | } | ||
| 257 | |||
| 258 | int | 202 | int |
| 259 | nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) | 203 | nouveau_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 | ||
| 25 | int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); | 23 | int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); |
| 26 | bool nouveau_fence_done(struct nouveau_fence *); | 24 | bool nouveau_fence_done(struct nouveau_fence *); |
| 27 | void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *); | ||
| 28 | int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); | 25 | int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); |
| 29 | int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); | 26 | int 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 | ||
| 91 | struct nv84_fence_chan { | 88 | struct 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 | ||
| 97 | struct nv84_fence_priv { | 93 | struct 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 | ||
| 35 | void | 39 | void |
| 36 | nouveau_gem_object_del(struct drm_gem_object *gem) | 40 | nouveau_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); | ||
| 102 | out: | 89 | out: |
| 103 | ttm_bo_unreserve(&nvbo->bo); | 90 | ttm_bo_unreserve(&nvbo->bo); |
| 104 | return ret; | 91 | return ret; |
| 105 | } | 92 | } |
| 106 | 93 | ||
| 94 | struct nouveau_gem_object_unmap { | ||
| 95 | struct nouveau_cli_work work; | ||
| 96 | struct nouveau_vma *vma; | ||
| 97 | }; | ||
| 98 | |||
| 107 | static void | 99 | static void |
| 108 | nouveau_gem_object_delete(void *data) | 100 | nouveau_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 | ||
| 116 | static void | 105 | static void |
| 117 | nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma) | 106 | nouveau_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 | |||
| 114 | static void | ||
| 115 | nouveau_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 | ||
| 146 | void | 151 | void |
| @@ -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 | |||
| 255 | nouveau_gem_ioctl_new(struct drm_device *dev, void *data, | 267 | nouveau_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 | |||
| 12 | static inline struct nouveau_bo * | 9 | static inline struct nouveau_bo * |
| 13 | nouveau_gem_object(struct drm_gem_object *gem) | 10 | nouveau_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 | |||
| 35 | int | ||
| 36 | nouveau_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 | |||
| 84 | void | ||
| 85 | nouveau_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 | |||
| 94 | int | ||
| 95 | nouveau_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 | |||
| 132 | int | ||
| 133 | nouveau_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 | |||
| 175 | void | ||
| 176 | nouveau_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 | |||
| 184 | int | ||
| 185 | nouveau_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> | ||
| 4 | struct ttm_dma_tt; | ||
| 5 | |||
| 6 | #include <nvif/mem.h> | ||
| 7 | #include <nvif/vmm.h> | ||
| 8 | |||
| 9 | static inline struct nouveau_mem * | ||
| 10 | nouveau_mem(struct ttm_mem_reg *reg) | ||
| 11 | { | ||
| 12 | return reg->mm_node; | ||
| 13 | } | ||
| 14 | |||
| 15 | struct 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 | |||
| 23 | int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, | ||
| 24 | struct ttm_mem_reg *); | ||
| 25 | void nouveau_mem_del(struct ttm_mem_reg *); | ||
| 26 | int nouveau_mem_vram(struct ttm_mem_reg *, bool contig, u8 page); | ||
| 27 | int nouveau_mem_host(struct ttm_mem_reg *, struct ttm_dma_tt *); | ||
| 28 | void nouveau_mem_fini(struct nouveau_mem *); | ||
| 29 | int 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 | ||
| 7 | struct nouveau_sgdma_be { | 8 | struct 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 | ||
| 15 | static void | 16 | static void |
| @@ -27,19 +28,20 @@ static int | |||
| 27 | nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) | 28 | nv04_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 | |||
| 47 | nv04_sgdma_unbind(struct ttm_tt *ttm) | 49 | nv04_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 | |||
| 61 | nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) | 63 | nv50_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 | ||
| 78 | static int | 69 | ret = nouveau_mem_host(reg, &nvbe->ttm); |
| 79 | nv50_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 | ||
| 85 | static struct ttm_backend_func nv50_sgdma_backend = { | 77 | static 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 | ||
| 35 | static int | 35 | static int |
| 36 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 36 | nouveau_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 | ||
| 44 | static int | 41 | static int |
| 45 | nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) | 42 | nouveau_manager_fini(struct ttm_mem_type_manager *man) |
| 46 | { | 43 | { |
| 47 | man->priv = NULL; | ||
| 48 | return 0; | 44 | return 0; |
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | static inline void | 47 | static void |
| 52 | nvkm_mem_node_cleanup(struct nvkm_mem *node) | 48 | nouveau_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 | ||
| 65 | static void | 53 | static void |
| 66 | nouveau_vram_manager_del(struct ttm_mem_type_manager *man, | 54 | nouveau_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 **)®->mm_node); | ||
| 73 | } | 57 | } |
| 74 | 58 | ||
| 75 | static int | 59 | static 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 | ||
| 109 | const struct ttm_mem_type_manager_func nouveau_vram_manager = { | 91 | const 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 | ||
| 116 | static int | 99 | static int |
| 117 | nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | ||
| 118 | { | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int | ||
| 123 | nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) | ||
| 124 | { | ||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | static void | ||
| 129 | nouveau_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 | |||
| 137 | static int | ||
| 138 | nouveau_gart_manager_new(struct ttm_mem_type_manager *man, | 100 | nouveau_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 | ||
| 181 | static void | ||
| 182 | nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, | ||
| 183 | struct drm_printer *printer) | ||
| 184 | { | ||
| 185 | } | ||
| 186 | |||
| 187 | const struct ttm_mem_type_manager_func nouveau_gart_manager = { | 119 | const 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> | ||
| 197 | static int | ||
| 198 | nv04_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 | |||
| 209 | static int | ||
| 210 | nv04_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 | |||
| 218 | static void | ||
| 219 | nv04_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 | |||
| 228 | static int | 127 | static int |
| 229 | nv04_gart_manager_new(struct ttm_mem_type_manager *man, | 128 | nv04_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 | ||
| 255 | static void | ||
| 256 | nv04_gart_manager_debug(struct ttm_mem_type_manager *man, | ||
| 257 | struct drm_printer *printer) | ||
| 258 | { | ||
| 259 | } | ||
| 260 | |||
| 261 | const struct ttm_mem_type_manager_func nv04_gart_manager = { | 158 | const 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 | ||
| 269 | int | 166 | int |
| @@ -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 | |||
| 27 | void | ||
| 28 | nouveau_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 | |||
| 36 | int | ||
| 37 | nouveau_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 | |||
| 47 | struct nouveau_vma * | ||
| 48 | nouveau_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 | |||
| 60 | void | ||
| 61 | nouveau_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 | |||
| 75 | int | ||
| 76 | nouveau_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 | |||
| 112 | done: | ||
| 113 | if (ret) | ||
| 114 | nouveau_vma_del(pvma); | ||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 118 | void | ||
| 119 | nouveau_vmm_fini(struct nouveau_vmm *vmm) | ||
| 120 | { | ||
| 121 | nvif_vmm_fini(&vmm->vmm); | ||
| 122 | vmm->cli = NULL; | ||
| 123 | } | ||
| 124 | |||
| 125 | int | ||
| 126 | nouveau_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> | ||
| 4 | struct nouveau_bo; | ||
| 5 | struct nouveau_mem; | ||
| 6 | |||
| 7 | struct 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 | |||
| 16 | struct nouveau_vma *nouveau_vma_find(struct nouveau_bo *, struct nouveau_vmm *); | ||
| 17 | int nouveau_vma_new(struct nouveau_bo *, struct nouveau_vmm *, | ||
| 18 | struct nouveau_vma **); | ||
| 19 | void nouveau_vma_del(struct nouveau_vma **); | ||
| 20 | int nouveau_vma_map(struct nouveau_vma *, struct nouveau_mem *); | ||
| 21 | void nouveau_vma_unmap(struct nouveau_vma *); | ||
| 22 | |||
| 23 | struct nouveau_vmm { | ||
| 24 | struct nouveau_cli *cli; | ||
| 25 | struct nvif_vmm vmm; | ||
| 26 | struct nvkm_vm *vm; | ||
| 27 | }; | ||
| 28 | |||
| 29 | int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *); | ||
| 30 | void 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 | ||
| 29 | int | 30 | int |
| 30 | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 31 | nv50_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 | |||
| 182 | nv84_fence_destroy(struct nouveau_drm *drm) | 168 | nv84_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 | ||
| 29 | int | 30 | int |
| 30 | nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | 31 | nvc0_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 | |||
| 2 | nvif-y += nvif/client.o | 2 | nvif-y += nvif/client.o |
| 3 | nvif-y += nvif/device.o | 3 | nvif-y += nvif/device.o |
| 4 | nvif-y += nvif/driver.o | 4 | nvif-y += nvif/driver.o |
| 5 | nvif-y += nvif/mem.o | ||
| 6 | nvif-y += nvif/mmu.o | ||
| 5 | nvif-y += nvif/notify.o | 7 | nvif-y += nvif/notify.o |
| 8 | nvif-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 | |||
| 27 | void | ||
| 28 | nvif_mem_fini(struct nvif_mem *mem) | ||
| 29 | { | ||
| 30 | nvif_object_fini(&mem->object); | ||
| 31 | } | ||
| 32 | |||
| 33 | int | ||
| 34 | nvif_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 | |||
| 72 | int | ||
| 73 | nvif_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 | |||
| 27 | void | ||
| 28 | nvif_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 | |||
| 36 | int | ||
| 37 | nvif_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 | |||
| 113 | done: | ||
| 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 | ||
| 168 | void | 168 | void |
| 169 | nvif_object_unmap(struct nvif_object *object) | 169 | nvif_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 | |||
| 181 | int | ||
| 182 | nvif_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 | |||
| 205 | void | ||
| 206 | nvif_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 | ||
| 191 | int | 220 | int |
| 192 | nvif_object_map(struct nvif_object *object) | 221 | nvif_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 | |||
| 27 | int | ||
| 28 | nvif_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 | |||
| 35 | int | ||
| 36 | nvif_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 | |||
| 64 | void | ||
| 65 | nvif_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 | |||
| 76 | int | ||
| 77 | nvif_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 | |||
| 107 | void | ||
| 108 | nvif_vmm_fini(struct nvif_vmm *vmm) | ||
| 109 | { | ||
| 110 | kfree(vmm->page); | ||
| 111 | nvif_object_fini(&vmm->object); | ||
| 112 | } | ||
| 113 | |||
| 114 | int | ||
| 115 | nvif_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 | |||
| 162 | done: | ||
| 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 | ||
| 129 | static int | ||
| 130 | nvkm_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 | |||
| 129 | static void * | 138 | static void * |
| 130 | nvkm_engine_dtor(struct nvkm_subdev *subdev) | 139 | nvkm_engine_dtor(struct nvkm_subdev *subdev) |
| 131 | { | 140 | { |
| @@ -138,6 +147,7 @@ nvkm_engine_dtor(struct nvkm_subdev *subdev) | |||
| 138 | static const struct nvkm_subdev_func | 147 | static const struct nvkm_subdev_func |
| 139 | nvkm_engine_func = { | 148 | nvkm_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 */ |
| 45 | static int | ||
| 46 | nvkm_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 | |||
| 45 | static u32 | 53 | static u32 |
| 46 | nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) | 54 | nvkm_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 | ||
| 72 | static const struct nvkm_gpuobj_func | 81 | static 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 | ||
| 79 | static void * | 89 | static void * |
| @@ -90,9 +100,19 @@ nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj) | |||
| 90 | static const struct nvkm_gpuobj_func | 100 | static const struct nvkm_gpuobj_func |
| 91 | nvkm_gpuobj_heap = { | 101 | nvkm_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 */ |
| 107 | static int | ||
| 108 | nvkm_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 | |||
| 96 | static u32 | 116 | static u32 |
| 97 | nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) | 117 | nvkm_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 | ||
| 123 | static const struct nvkm_gpuobj_func | 144 | static 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 | ||
| 130 | static void * | 152 | static void * |
| @@ -143,6 +165,7 @@ nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) | |||
| 143 | static const struct nvkm_gpuobj_func | 165 | static const struct nvkm_gpuobj_func |
| 144 | nvkm_gpuobj_func = { | 166 | nvkm_gpuobj_func = { |
| 145 | .acquire = nvkm_gpuobj_acquire, | 167 | .acquire = nvkm_gpuobj_acquire, |
| 168 | .map = nvkm_gpuobj_map, | ||
| 146 | }; | 169 | }; |
| 147 | 170 | ||
| 148 | static int | 171 | static 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 | ||
| 191 | void | 214 | void |
| @@ -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 | ||
| 221 | int | ||
| 222 | nvkm_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 | |||
| 232 | void | ||
| 233 | nvkm_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 | ||
| 27 | void | 29 | void |
| 30 | nvkm_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 | |||
| 47 | int | ||
| 48 | nvkm_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 | |||
| 98 | void | ||
| 28 | nvkm_memory_ctor(const struct nvkm_memory_func *func, | 99 | nvkm_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 | |||
| 106 | static void | ||
| 107 | nvkm_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 | ||
| 34 | void | 117 | void |
| 35 | nvkm_memory_del(struct nvkm_memory **pmemory) | 118 | nvkm_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 | ||
| 127 | struct nvkm_memory * | ||
| 128 | nvkm_memory_ref(struct nvkm_memory *memory) | ||
| 129 | { | ||
| 130 | if (memory) | ||
| 131 | kref_get(&memory->kref); | ||
| 132 | return memory; | ||
| 133 | } | ||
| 134 | |||
| 46 | int | 135 | int |
| 47 | nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target, | 136 | nvkm_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 | ||
| 239 | int | 239 | int |
| 240 | nvkm_mm_init(struct nvkm_mm *mm, u32 offset, u32 length, u32 block) | 240 | nvkm_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 | ||
| 104 | int | 104 | int |
| 105 | nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size) | 105 | nvkm_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 | |||
| 113 | int | ||
| 114 | nvkm_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 | ||
| 39 | static int | 39 | static int |
| 40 | nvkm_oproxy_map(struct nvkm_object *object, u64 *addr, u32 *size) | 40 | nvkm_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 | |||
| 47 | static int | ||
| 48 | nvkm_oproxy_unmap(struct nvkm_object *object) | ||
| 49 | { | ||
| 50 | return nvkm_object_unmap(nvkm_oproxy(object)->object); | ||
| 43 | } | 51 | } |
| 44 | 52 | ||
| 45 | static int | 53 | static 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 | ||
| 25 | static u32 | 26 | static u32 |
| 26 | nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) | 27 | nvkm_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 = { | |||
| 1958 | static const struct nvkm_device_chip | 1958 | static const struct nvkm_device_chip |
| 1959 | nv117_chipset = { | 1959 | nv117_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 = { | |||
| 1992 | static const struct nvkm_device_chip | 1992 | static const struct nvkm_device_chip |
| 1993 | nv118_chipset = { | 1993 | nv118_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 = { | |||
| 2026 | static const struct nvkm_device_chip | 2026 | static const struct nvkm_device_chip |
| 2027 | nv120_chipset = { | 2027 | nv120_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 = { | |||
| 2061 | static const struct nvkm_device_chip | 2061 | static const struct nvkm_device_chip |
| 2062 | nv124_chipset = { | 2062 | nv124_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 = { | |||
| 2096 | static const struct nvkm_device_chip | 2096 | static const struct nvkm_device_chip |
| 2097 | nv126_chipset = { | 2097 | nv126_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 = { | |||
| 2131 | static const struct nvkm_device_chip | 2131 | static const struct nvkm_device_chip |
| 2132 | nv12b_chipset = { | 2132 | nv12b_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 = { | |||
| 2156 | static const struct nvkm_device_chip | 2156 | static const struct nvkm_device_chip |
| 2157 | nv130_chipset = { | 2157 | nv130_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 = { | |||
| 2190 | static const struct nvkm_device_chip | 2191 | static const struct nvkm_device_chip |
| 2191 | nv132_chipset = { | 2192 | nv132_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 = { | |||
| 2224 | static const struct nvkm_device_chip | 2226 | static const struct nvkm_device_chip |
| 2225 | nv134_chipset = { | 2227 | nv134_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 = { | |||
| 2258 | static const struct nvkm_device_chip | 2261 | static const struct nvkm_device_chip |
| 2259 | nv136_chipset = { | 2262 | nv136_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 = { | |||
| 2292 | static const struct nvkm_device_chip | 2296 | static const struct nvkm_device_chip |
| 2293 | nv137_chipset = { | 2297 | nv137_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 = { | |||
| 2326 | static const struct nvkm_device_chip | 2331 | static const struct nvkm_device_chip |
| 2327 | nv138_chipset = { | 2332 | nv138_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 = { | |||
| 2355 | static const struct nvkm_device_chip | 2361 | static const struct nvkm_device_chip |
| 2356 | nv13b_chipset = { | 2362 | nv13b_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 | ||
| 6 | struct nvkm_control { | 6 | struct 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 | ||
| 222 | static int | 222 | static 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 | ||
| 208 | static int | 208 | static int |
| 209 | nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size) | 209 | nvkm_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 | ||
| 193 | static int | 193 | static int |
| 194 | nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) | 194 | nv50_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 | ||
| 6 | struct nv50_disp_chan { | 7 | struct 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 | ||
| 282 | static void | ||
| 283 | nvkm_fifo_preinit(struct nvkm_engine *engine) | ||
| 284 | { | ||
| 285 | nvkm_mc_reset(engine->subdev.device, NVKM_ENGINE_FIFO); | ||
| 286 | } | ||
| 287 | |||
| 281 | static int | 288 | static int |
| 282 | nvkm_fifo_init(struct nvkm_engine *engine) | 289 | nvkm_fifo_init(struct nvkm_engine *engine) |
| 283 | { | 290 | { |
| @@ -302,6 +309,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) | |||
| 302 | static const struct nvkm_engine_func | 309 | static const struct nvkm_engine_func |
| 303 | nvkm_fifo = { | 310 | nvkm_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 | ||
| 255 | static int | 255 | static int |
| 256 | nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) | 256 | nvkm_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 = { | |||
| 347 | int | 352 | int |
| 348 | nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, | 353 | nvkm_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 | ||
| 231 | int | 231 | int |
| 232 | g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, | 232 | g84_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 * | |||
| 206 | nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) | 206 | nv50_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 | ||
| 231 | int | 230 | int |
| 232 | nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, | 231 | nv50_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 | ||
| 21 | int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, | 20 | int 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 *); |
| 23 | void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); | 22 | void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); |
| 24 | void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); | 23 | void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); |
| 25 | void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); | 24 | void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); |
| 26 | void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); | 25 | void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); |
| 27 | 26 | ||
| 28 | int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, | 27 | int 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 | ||
| 31 | extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass; | 30 | extern 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 | ||
| 595 | static void | 596 | static 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 * | |||
| 639 | gf100_fifo_dtor(struct nvkm_fifo *base) | 640 | gf100_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 | ||
| 846 | static void | 846 | static 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 * | |||
| 876 | gk104_fifo_dtor(struct nvkm_fifo *base) | 876 | gk104_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 | ||
| 153 | static void | 158 | static void |
| @@ -190,10 +195,7 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) | |||
| 190 | static void * | 195 | static void * |
| 191 | gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) | 196 | gf100_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 | ||
| 199 | static const struct nvkm_fifo_chan_func | 201 | static 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 | ||
| 165 | static void | 170 | static void |
| @@ -203,10 +208,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) | |||
| 203 | static void * | 208 | static void * |
| 204 | gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) | 209 | gk104_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 | ||
| 212 | static const struct nvkm_fifo_chan_func | 214 | static const struct nvkm_fifo_chan_func |
| @@ -229,17 +231,19 @@ struct gk104_fifo_chan_func { | |||
| 229 | static int | 231 | static int |
| 230 | gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, | 232 | gk104_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 * | |||
| 100 | nv50_fifo_dtor(struct nvkm_fifo *base) | 100 | nv50_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 | ||
| 988 | int | 988 | int |
| 989 | gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, u32 access) | 989 | gf100_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 | |||
| 1028 | gf100_grctx_generate_bundle(struct gf100_grctx *info) | 1028 | gf100_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 | |||
| 1041 | gf100_grctx_generate_pagepool(struct gf100_grctx *info) | 1040 | gf100_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 | |||
| 1270 | int | 1269 | int |
| 1271 | gf100_grctx_generate(struct gf100_gr *gr) | 1270 | gf100_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 | ||
| 1382 | done: | 1381 | done: |
| 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 | ||
| 14 | int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, u32 access); | 14 | int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv); |
| 15 | void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int); | 15 | void 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 | |||
| 861 | gk104_grctx_generate_pagepool(struct gf100_grctx *info) | 860 | gk104_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 | |||
| 881 | gm107_grctx_generate_pagepool(struct gf100_grctx *info) | 880 | gm107_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 | |||
| 33 | gp100_grctx_generate_pagepool(struct gf100_grctx *info) | 33 | gp100_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 | ||
| 1916 | void | ||
| 1917 | gf100_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 | |||
| 1906 | int | 1932 | int |
| 1907 | gf100_gr_init(struct gf100_gr *gr) | 1933 | gf100_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 = { | |||
| 2036 | static const struct gf100_gr_func | 2054 | static const struct gf100_gr_func |
| 2037 | gf100_gr = { | 2055 | gf100_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 @@ | |||
| 45 | struct gf100_gr_data { | 45 | struct 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 | ||
| 51 | struct gf100_gr_mmio { | 51 | struct gf100_gr_mmio { |
| @@ -156,18 +156,20 @@ int gp100_gr_init(struct gf100_gr *); | |||
| 156 | void gp100_gr_init_rop_active_fbps(struct gf100_gr *); | 156 | void 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 | ||
| 160 | struct gf100_gr_chan { | 161 | struct 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[]; | |||
| 253 | extern const struct gf100_gr_init gf100_gr_init_be_0[]; | 255 | extern const struct gf100_gr_init gf100_gr_init_be_0[]; |
| 254 | extern const struct gf100_gr_init gf100_gr_init_fe_1[]; | 256 | extern const struct gf100_gr_init gf100_gr_init_fe_1[]; |
| 255 | extern const struct gf100_gr_init gf100_gr_init_pe_1[]; | 257 | extern const struct gf100_gr_init gf100_gr_init_pe_1[]; |
| 258 | void gf100_gr_init_gpc_mmu(struct gf100_gr *); | ||
| 256 | 259 | ||
| 257 | extern const struct gf100_gr_init gf104_gr_init_ds_0[]; | 260 | extern const struct gf100_gr_init gf104_gr_init_ds_0[]; |
| 258 | extern const struct gf100_gr_init gf104_gr_init_tex_0[]; | 261 | extern 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[] = { | |||
| 115 | static const struct gf100_gr_func | 115 | static const struct gf100_gr_func |
| 116 | gf104_gr = { | 116 | gf104_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[] = { | |||
| 106 | static const struct gf100_gr_func | 106 | static const struct gf100_gr_func |
| 107 | gf108_gr = { | 107 | gf108_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[] = { | |||
| 87 | static const struct gf100_gr_func | 87 | static const struct gf100_gr_func |
| 88 | gf110_gr = { | 88 | gf110_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 = { | |||
| 123 | static const struct gf100_gr_func | 123 | static const struct gf100_gr_func |
| 124 | gf117_gr = { | 124 | gf117_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[] = { | |||
| 178 | static const struct gf100_gr_func | 178 | static const struct gf100_gr_func |
| 179 | gf119_gr = { | 179 | gf119_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 | |||
| 207 | gk104_gr_init(struct gf100_gr *gr) | 205 | gk104_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 = { | |||
| 339 | static const struct gf100_gr_func | 329 | static const struct gf100_gr_func |
| 340 | gk104_gr = { | 330 | gk104_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 = { | |||
| 183 | static const struct gf100_gr_func | 183 | static const struct gf100_gr_func |
| 184 | gk110_gr = { | 184 | gk110_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[] = { | |||
| 103 | static const struct gf100_gr_func | 103 | static const struct gf100_gr_func |
| 104 | gk110b_gr = { | 104 | gk110b_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 = { | |||
| 162 | static const struct gf100_gr_func | 162 | static const struct gf100_gr_func |
| 163 | gk208_gr = { | 163 | gk208_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 * | |||
| 59 | nv20_gr_chan_dtor(struct nvkm_object *object) | 59 | nv20_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 * | |||
| 323 | nv20_gr_dtor(struct nvkm_gr *base) | 323 | nv20_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 *); | |||
| 19 | int nv30_gr_init(struct nvkm_gr *); | 19 | int 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 | ||
| 23 | struct nv20_gr_chan { | 24 | struct 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 *); | |||
| 16 | u64 nv40_gr_units(struct nvkm_gr *); | 16 | u64 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 | ||
| 20 | struct nv40_gr_chan { | 21 | struct 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 *); | |||
| 19 | int g84_gr_tlb_flush(struct nvkm_gr *); | 19 | int 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 | ||
| 23 | struct nv50_gr_chan { | 24 | struct 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 | ||
| 22 | struct nv31_mpeg_chan { | 23 | struct 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 | ||
| 71 | struct nvkm_perfdom { | 72 | struct 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 | |||
| 7 | struct nvkm_sw_chan { | 9 | struct 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 | ||
| 6 | struct nvkm_nvsw { | 6 | struct 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 | ||
| 62 | void | 62 | void |
| 63 | nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *inst) | 63 | nvkm_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 | ||
| 182 | static void | 182 | static void |
| 183 | nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) | 183 | nvkm_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 | |||
| 3 | nvkm-y += nvkm/subdev/bar/g84.o | 3 | nvkm-y += nvkm/subdev/bar/g84.o |
| 4 | nvkm-y += nvkm/subdev/bar/gf100.o | 4 | nvkm-y += nvkm/subdev/bar/gf100.o |
| 5 | nvkm-y += nvkm/subdev/bar/gk20a.o | 5 | nvkm-y += nvkm/subdev/bar/gk20a.o |
| 6 | nvkm-y += nvkm/subdev/bar/gm107.o | ||
| 7 | nvkm-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 | ||
| 33 | struct nvkm_vm * | 33 | struct nvkm_vmm * |
| 34 | nvkm_bar_kmap(struct nvkm_bar *bar) | 34 | nvkm_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 | |
| 39 | struct nvkm_vmm * | ||
| 40 | nvkm_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 | ||
| 42 | int | 51 | void |
| 43 | nvkm_bar_umap(struct nvkm_bar *bar, u64 size, int type, struct nvkm_vma *vma) | 52 | nvkm_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 | |||
| 61 | void | ||
| 62 | nvkm_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 | ||
| 48 | static int | 72 | static int |
| 49 | nvkm_bar_oneinit(struct nvkm_subdev *subdev) | 73 | nvkm_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 | ||
| 55 | static int | 80 | static int |
| 56 | nvkm_bar_init(struct nvkm_subdev *subdev) | 81 | nvkm_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 | |||
| 91 | static int | ||
| 92 | nvkm_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 | ||
| 62 | static void * | 98 | static void * |
| 63 | nvkm_bar_dtor(struct nvkm_subdev *subdev) | 99 | nvkm_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 | ||
| 76 | void | 114 | void |
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 | ||
| 31 | static struct nvkm_vm * | 31 | struct nvkm_vmm * |
| 32 | gf100_bar_kmap(struct nvkm_bar *base) | 32 | gf100_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 | ||
| 37 | int | 37 | void |
| 38 | gf100_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) | 38 | gf100_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 | |||
| 45 | void | ||
| 46 | gf100_bar_bar1_fini(struct nvkm_bar *bar) | ||
| 39 | { | 47 | { |
| 48 | nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000); | ||
| 49 | } | ||
| 50 | |||
| 51 | void | ||
| 52 | gf100_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 | |||
| 60 | struct nvkm_vmm * | ||
| 61 | gf100_bar_bar2_vmm(struct nvkm_bar *base) | ||
| 62 | { | ||
| 63 | return gf100_bar(base)->bar[0].vmm; | ||
| 64 | } | ||
| 65 | |||
| 66 | void | ||
| 67 | gf100_bar_bar2_fini(struct nvkm_bar *bar) | ||
| 68 | { | ||
| 69 | nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000); | ||
| 70 | } | ||
| 71 | |||
| 72 | void | ||
| 73 | gf100_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 | ||
| 44 | static int | 83 | static int |
| 45 | gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, | 84 | gf100_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 | ||
| 97 | int | 120 | int |
| 98 | gf100_bar_oneinit(struct nvkm_bar *base) | 121 | gf100_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 | ||
| 120 | int | ||
| 121 | gf100_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 | |||
| 143 | void * | 146 | void * |
| 144 | gf100_bar_dtor(struct nvkm_bar *base) | 147 | gf100_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 | |||
| 175 | gf100_bar_func = { | 175 | gf100_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 | ||
| 6 | struct gf100_bar_vm { | 6 | struct 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 | ||
| 12 | struct gf100_bar { | 11 | struct 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 | ||
| 18 | int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, | 17 | int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, |
| 19 | int, struct nvkm_bar **); | 18 | int, struct nvkm_bar **); |
| 20 | void *gf100_bar_dtor(struct nvkm_bar *); | 19 | void *gf100_bar_dtor(struct nvkm_bar *); |
| 21 | int gf100_bar_oneinit(struct nvkm_bar *); | 20 | int gf100_bar_oneinit(struct nvkm_bar *); |
| 22 | int gf100_bar_init(struct nvkm_bar *); | 21 | void gf100_bar_bar1_init(struct nvkm_bar *); |
| 23 | int gf100_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); | 22 | void gf100_bar_bar1_wait(struct nvkm_bar *); |
| 23 | struct nvkm_vmm *gf100_bar_bar1_vmm(struct nvkm_bar *); | ||
| 24 | void gf100_bar_bar2_init(struct nvkm_bar *); | ||
| 25 | struct 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 | |||
| 25 | gk20a_bar_func = { | 25 | gk20a_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 | |||
| 26 | void | ||
| 27 | gm107_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 | |||
| 36 | static void | ||
| 37 | gm107_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 | |||
| 46 | static const struct nvkm_bar_func | ||
| 47 | gm107_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 | |||
| 61 | int | ||
| 62 | gm107_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 | |||
| 24 | static const struct nvkm_bar_func | ||
| 25 | gm20b_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 | |||
| 35 | int | ||
| 36 | gm20b_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 | ||
| 31 | struct nvkm_vm * | ||
| 32 | nv50_bar_kmap(struct nvkm_bar *base) | ||
| 33 | { | ||
| 34 | return nv50_bar(base)->bar3_vm; | ||
| 35 | } | ||
| 36 | |||
| 37 | int | ||
| 38 | nv50_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 | |||
| 44 | static void | 31 | static void |
| 45 | nv50_bar_flush(struct nvkm_bar *base) | 32 | nv50_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 | ||
| 46 | struct nvkm_vmm * | ||
| 47 | nv50_bar_bar1_vmm(struct nvkm_bar *base) | ||
| 48 | { | ||
| 49 | return nv50_bar(base)->bar1_vmm; | ||
| 50 | } | ||
| 51 | |||
| 52 | void | ||
| 53 | nv50_bar_bar1_wait(struct nvkm_bar *base) | ||
| 54 | { | ||
| 55 | nvkm_bar_flush(base); | ||
| 56 | } | ||
| 57 | |||
| 58 | void | ||
| 59 | nv50_bar_bar1_fini(struct nvkm_bar *bar) | ||
| 60 | { | ||
| 61 | nvkm_wr32(bar->subdev.device, 0x001708, 0x00000000); | ||
| 62 | } | ||
| 63 | |||
| 64 | void | ||
| 65 | nv50_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 | |||
| 72 | struct nvkm_vmm * | ||
| 73 | nv50_bar_bar2_vmm(struct nvkm_bar *base) | ||
| 74 | { | ||
| 75 | return nv50_bar(base)->bar2_vmm; | ||
| 76 | } | ||
| 77 | |||
| 78 | void | ||
| 79 | nv50_bar_bar2_fini(struct nvkm_bar *bar) | ||
| 80 | { | ||
| 81 | nvkm_wr32(bar->subdev.device, 0x00170c, 0x00000000); | ||
| 82 | } | ||
| 83 | |||
| 84 | void | ||
| 85 | nv50_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 | |||
| 94 | void | ||
| 95 | nv50_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 | |||
| 59 | int | 105 | int |
| 60 | nv50_bar_oneinit(struct nvkm_bar *base) | 106 | nv50_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 | ||
| 147 | int | ||
| 148 | nv50_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 | |||
| 172 | void * | 195 | void * |
| 173 | nv50_bar_dtor(struct nvkm_bar *base) | 196 | nv50_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 | ||
| 18 | int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, | 18 | int 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 **); |
| 20 | void *nv50_bar_dtor(struct nvkm_bar *); | 20 | void *nv50_bar_dtor(struct nvkm_bar *); |
| 21 | int nv50_bar_oneinit(struct nvkm_bar *); | 21 | int nv50_bar_oneinit(struct nvkm_bar *); |
| 22 | int nv50_bar_init(struct nvkm_bar *); | 22 | void nv50_bar_init(struct nvkm_bar *); |
| 23 | struct nvkm_vm *nv50_bar_kmap(struct nvkm_bar *); | 23 | void nv50_bar_bar1_init(struct nvkm_bar *); |
| 24 | int nv50_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); | 24 | void nv50_bar_bar1_wait(struct nvkm_bar *); |
| 25 | void nv50_bar_unmap(struct nvkm_bar *, struct nvkm_vma *); | 25 | struct nvkm_vmm *nv50_bar_bar1_vmm(struct nvkm_bar *); |
| 26 | void nv50_bar_bar2_init(struct nvkm_bar *); | ||
| 27 | struct 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 *, | |||
| 9 | struct nvkm_bar_func { | 9 | struct 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 | ||
| 24 | void nv50_bar_bar1_fini(struct nvkm_bar *); | ||
| 25 | void nv50_bar_bar2_fini(struct nvkm_bar *); | ||
| 26 | |||
| 18 | void g84_bar_flush(struct nvkm_bar *); | 27 | void g84_bar_flush(struct nvkm_bar *); |
| 28 | |||
| 29 | void gf100_bar_bar1_fini(struct nvkm_bar *); | ||
| 30 | void gf100_bar_bar2_fini(struct nvkm_bar *); | ||
| 31 | |||
| 32 | void 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 | |||
| 2276 | int | 2276 | int |
| 2277 | nvbios_exec(struct nvbios_init *init) | 2277 | nvbios_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 | ||
| 34 | bool | ||
| 35 | nvkm_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) | ||
| 36 | { | ||
| 37 | return fb->func->memtype_valid(fb, memtype); | ||
| 38 | } | ||
| 39 | |||
| 40 | void | 34 | void |
| 41 | nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) | 35 | nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) |
| 42 | { | 36 | { |
| @@ -100,6 +94,7 @@ static int | |||
| 100 | nvkm_fb_oneinit(struct nvkm_subdev *subdev) | 94 | nvkm_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 | ||
| 121 | static int | 125 | static 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 | ||
| 182 | int | 193 | int |
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 @@ | |||
| 27 | static const struct nv50_fb_func | 27 | static const struct nv50_fb_func |
| 28 | g84_fb = { | 28 | g84_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 | ||
| 30 | extern const u8 gf100_pte_storage_type_map[256]; | ||
| 31 | |||
| 32 | bool | ||
| 33 | gf100_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 | |||
| 39 | void | 30 | void |
| 40 | gf100_fb_intr(struct nvkm_fb *base) | 31 | gf100_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 | ||
| 83 | void | 74 | int |
| 84 | gf100_fb_init_page(struct nvkm_fb *fb) | 75 | gf100_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 | ||
| 99 | void | 87 | void |
| @@ -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 | ||
| 149 | int | 137 | int |
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 | ||
| 18 | void gp100_fb_init(struct nvkm_fb *); | 18 | void gp100_fb_init(struct nvkm_fb *); |
| 19 | 19 | ||
| 20 | void gm200_fb_init_page(struct nvkm_fb *fb); | ||
| 21 | void gm200_fb_init(struct nvkm_fb *base); | 20 | void 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 | ||
| 38 | int | 38 | int |
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 | ||
| 38 | int | 38 | int |
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 | ||
| 36 | int | 36 | int |
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 | ||
| 38 | int | 38 | int |
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 | ||
| 29 | void | 29 | int |
| 30 | gm200_fb_init_page(struct nvkm_fb *fb) | 30 | gm200_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 | ||
| 47 | void | 43 | void |
| @@ -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 | ||
| 75 | int | 71 | int |
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 | ||
| 36 | int | 36 | int |
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 | ||
| 65 | int | 64 | int |
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 | ||
| 39 | int | 38 | int |
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 | ||
| 34 | int | 33 | int |
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 @@ | |||
| 27 | static const struct nv50_fb_func | 27 | static const struct nv50_fb_func |
| 28 | gt215_fb = { | 28 | gt215_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 | ||
| 28 | bool | ||
| 29 | nv04_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags) | ||
| 30 | { | ||
| 31 | if (!(tile_flags & 0xff00)) | ||
| 32 | return true; | ||
| 33 | return false; | ||
| 34 | } | ||
| 35 | |||
| 36 | static void | 28 | static void |
| 37 | nv04_fb_init(struct nvkm_fb *fb) | 29 | nv04_fb_init(struct nvkm_fb *fb) |
| 38 | { | 30 | { |
| @@ -49,7 +41,6 @@ static const struct nvkm_fb_func | |||
| 49 | nv04_fb = { | 41 | nv04_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 | ||
| 55 | int | 46 | int |
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 | ||
| 67 | int | 66 | int |
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 | ||
| 39 | int | 38 | int |
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 | ||
| 69 | void | 69 | void |
| @@ -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 | ||
| 80 | u32 | ||
| 81 | nv20_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 | |||
| 80 | static const struct nvkm_fb_func | 87 | static const struct nvkm_fb_func |
| 81 | nv20_fb = { | 88 | nv20_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 | ||
| 91 | int | 98 | int |
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 | ||
| 45 | static const struct nvkm_fb_func | 45 | static const struct nvkm_fb_func |
| 46 | nv25_fb = { | 46 | nv25_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 | ||
| 56 | int | 56 | int |
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 | ||
| 117 | static const struct nvkm_fb_func | 117 | static const struct nvkm_fb_func |
| 118 | nv30_fb = { | 118 | nv30_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 | ||
| 129 | int | 129 | int |
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 | ||
| 46 | static const struct nvkm_fb_func | 46 | static const struct nvkm_fb_func |
| 47 | nv35_fb = { | 47 | nv35_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 | ||
| 58 | int | 58 | int |
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 | ||
| 46 | static const struct nvkm_fb_func | 46 | static const struct nvkm_fb_func |
| 47 | nv36_fb = { | 47 | nv36_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 | ||
| 58 | int | 58 | int |
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 | ||
| 52 | static const struct nvkm_fb_func | 52 | static const struct nvkm_fb_func |
| 53 | nv40_fb = { | 53 | nv40_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 | ||
| 64 | int | 64 | int |
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 | ||
| 46 | static const struct nvkm_fb_func | 46 | static const struct nvkm_fb_func |
| 47 | nv41_fb = { | 47 | nv41_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 | ||
| 58 | int | 58 | int |
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 | ||
| 68 | int | 67 | int |
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 | ||
| 54 | int | 53 | int |
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 | ||
| 29 | static const struct nvkm_fb_func | 29 | static const struct nvkm_fb_func |
| 30 | nv47_fb = { | 30 | nv47_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 | ||
| 41 | int | 41 | int |
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 | ||
| 29 | static const struct nvkm_fb_func | 29 | static const struct nvkm_fb_func |
| 30 | nv49_fb = { | 30 | nv49_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 | ||
| 41 | int | 41 | int |
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 | ||
| 40 | int | 39 | int |
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 | ||
| 31 | int | ||
| 32 | nv50_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 | |||
| 43 | static int | 31 | static int |
| 44 | nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram) | 32 | nv50_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 | ||
| 50 | static bool | ||
| 51 | nv50_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) | ||
| 52 | { | ||
| 53 | return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | static const struct nvkm_enum vm_dispatch_subclients[] = { | 38 | static 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 | ||
| 229 | static u32 | ||
| 230 | nv50_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 | |||
| 247 | static void * | 238 | static void * |
| 248 | nv50_fb_dtor(struct nvkm_fb *base) | 239 | nv50_fb_dtor(struct nvkm_fb *base) |
| 249 | { | 240 | { |
| @@ -262,11 +253,11 @@ nv50_fb_dtor(struct nvkm_fb *base) | |||
| 262 | static const struct nvkm_fb_func | 253 | static const struct nvkm_fb_func |
| 263 | nv50_fb_ = { | 254 | nv50_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 | ||
| 272 | int | 263 | int |
| @@ -287,6 +278,7 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device, | |||
| 287 | static const struct nv50_fb_func | 278 | static const struct nv50_fb_func |
| 288 | nv50_fb = { | 279 | nv50_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 | ||
| 13 | struct nv50_fb_func { | 13 | struct 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 | ||
| 18 | int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index, | 19 | int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index, |
| 19 | struct nvkm_fb **pfb); | 20 | struct nvkm_fb **pfb); |
| 20 | extern 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 | ||
| 7 | struct nvkm_fb_func { | 7 | struct 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 | ||
| 30 | void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, | 31 | void 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 **); |
| 34 | int nvkm_fb_bios_memtype(struct nvkm_bios *); | 35 | int nvkm_fb_bios_memtype(struct nvkm_bios *); |
| 35 | 36 | ||
| 36 | bool nv04_fb_memtype_valid(struct nvkm_fb *, u32 memtype); | ||
| 37 | |||
| 38 | void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, | 37 | void 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 *); |
| 40 | void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); | 39 | void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); |
| 41 | void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); | 40 | void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); |
| 42 | 41 | ||
| 42 | u32 nv20_fb_tags(struct nvkm_fb *); | ||
| 43 | void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, | 43 | void 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 *); |
| 45 | void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); | 45 | void 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 | ||
| 64 | int gf100_fb_oneinit(struct nvkm_fb *); | 64 | int gf100_fb_oneinit(struct nvkm_fb *); |
| 65 | void gf100_fb_init_page(struct nvkm_fb *); | 65 | int gf100_fb_init_page(struct nvkm_fb *); |
| 66 | bool gf100_fb_memtype_valid(struct nvkm_fb *, u32); | ||
| 67 | 66 | ||
| 68 | void gm200_fb_init_page(struct nvkm_fb *); | 67 | int 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 | |||
| 30 | struct nvkm_vram { | ||
| 31 | struct nvkm_memory memory; | ||
| 32 | struct nvkm_ram *ram; | ||
| 33 | u8 page; | ||
| 34 | struct nvkm_mm_node *mn; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static int | ||
| 38 | nvkm_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 | |||
| 51 | static u64 | ||
| 52 | nvkm_vram_size(struct nvkm_memory *memory) | ||
| 53 | { | ||
| 54 | return (u64)nvkm_mm_size(nvkm_vram(memory)->mn) << NVKM_RAM_MM_SHIFT; | ||
| 55 | } | ||
| 56 | |||
| 57 | static u64 | ||
| 58 | nvkm_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 | |||
| 66 | static u8 | ||
| 67 | nvkm_vram_page(struct nvkm_memory *memory) | ||
| 68 | { | ||
| 69 | return nvkm_vram(memory)->page; | ||
| 70 | } | ||
| 71 | |||
| 72 | static enum nvkm_memory_target | ||
| 73 | nvkm_vram_target(struct nvkm_memory *memory) | ||
| 74 | { | ||
| 75 | return NVKM_MEM_TARGET_VRAM; | ||
| 76 | } | ||
| 77 | |||
| 78 | static void * | ||
| 79 | nvkm_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 | |||
| 93 | static const struct nvkm_memory_func | ||
| 94 | nvkm_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 | |||
| 103 | int | ||
| 104 | nvkm_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 | |||
| 26 | int | 150 | int |
| 27 | nvkm_ram_init(struct nvkm_ram *ram) | 151 | nvkm_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 | ||
| 48 | int | 171 | int |
| 49 | nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, | 172 | nvkm_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 | ||
| 92 | int | 207 | int |
| 93 | nvkm_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, | 208 | nvkm_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 | ||
| 5 | int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, | 5 | int 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 *); | ||
| 8 | int nvkm_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, | 7 | int 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 **); | ||
| 11 | void nvkm_ram_del(struct nvkm_ram **); | 9 | void nvkm_ram_del(struct nvkm_ram **); |
| 12 | int nvkm_ram_init(struct nvkm_ram *); | 10 | int nvkm_ram_init(struct nvkm_ram *); |
| 13 | 11 | ||
| @@ -15,9 +13,6 @@ extern const struct nvkm_ram_func nv04_ram_func; | |||
| 15 | 13 | ||
| 16 | int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, | 14 | int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, |
| 17 | struct nvkm_ram *); | 15 | struct nvkm_ram *); |
| 18 | int nv50_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); | ||
| 19 | void nv50_ram_put(struct nvkm_ram *, struct nvkm_mem **); | ||
| 20 | void __nv50_ram_put(struct nvkm_ram *, struct nvkm_mem *); | ||
| 21 | 16 | ||
| 22 | int gf100_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, | 17 | int 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 *, | |||
| 28 | u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, | 23 | u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, |
| 29 | struct nvkm_device *, int, int *); | 24 | struct nvkm_device *, int, int *); |
| 30 | u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int); | 25 | u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int); |
| 31 | int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); | ||
| 32 | void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); | ||
| 33 | int gf100_ram_init(struct nvkm_ram *); | 26 | int gf100_ram_init(struct nvkm_ram *); |
| 34 | int gf100_ram_calc(struct nvkm_ram *, u32); | 27 | int gf100_ram_calc(struct nvkm_ram *, u32); |
| 35 | int gf100_ram_prog(struct nvkm_ram *); | 28 | int 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 | ||
| 37 | struct gf100_ramfuc { | 36 | struct 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 | ||
| 423 | void | ||
| 424 | gf100_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 | |||
| 442 | int | ||
| 443 | gf100_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 | |||
| 503 | int | 422 | int |
| 504 | gf100_ram_init(struct nvkm_ram *base) | 423 | gf100_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 | ||
| 91 | int | 89 | int |
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 | ||
| 92 | struct gt215_ram { | 93 | struct 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) | |||
| 336 | static void | 337 | static void |
| 337 | gt215_link_train_fini(struct gt215_ram *ram) | 338 | gt215_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 | |||
| 931 | gt215_ram_func = { | 931 | gt215_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) | |||
| 53 | static const struct nvkm_ram_func | 53 | static const struct nvkm_ram_func |
| 54 | mcp77_ram_func = { | 54 | mcp77_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 | ||
| 60 | int | 58 | int |
| @@ -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 | ||
| 188 | int | 188 | int |
| 189 | nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type type, u64 size, | 189 | nv40_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 | ||
| 199 | int | 199 | int |
| @@ -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 | ||
| 12 | int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64, u32, | 12 | int 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 | ||
| 496 | void | ||
| 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 | |||
| 508 | void | ||
| 509 | nv50_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 | |||
| 524 | int | ||
| 525 | nv50_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 | |||
| 586 | static const struct nvkm_ram_func | 496 | static const struct nvkm_ram_func |
| 587 | nv50_ram_func = { | 497 | nv50_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 | |||
| 34 | struct 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 | |||
| 43 | static enum nvkm_memory_target | ||
| 44 | nvkm_instobj_target(struct nvkm_memory *memory) | ||
| 45 | { | ||
| 46 | memory = nvkm_instobj(memory)->parent; | ||
| 47 | return nvkm_memory_target(memory); | ||
| 48 | } | ||
| 49 | |||
| 50 | static u64 | ||
| 51 | nvkm_instobj_addr(struct nvkm_memory *memory) | ||
| 52 | { | ||
| 53 | memory = nvkm_instobj(memory)->parent; | ||
| 54 | return nvkm_memory_addr(memory); | ||
| 55 | } | ||
| 56 | |||
| 57 | static u64 | ||
| 58 | nvkm_instobj_size(struct nvkm_memory *memory) | ||
| 59 | { | ||
| 60 | memory = nvkm_instobj(memory)->parent; | ||
| 61 | return nvkm_memory_size(memory); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void | 31 | static void |
| 65 | nvkm_instobj_release(struct nvkm_memory *memory) | 32 | nvkm_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; | |
| 71 | static void __iomem * | ||
| 72 | nvkm_instobj_acquire(struct nvkm_memory *memory) | ||
| 73 | { | ||
| 74 | return nvkm_instobj(memory)->map; | ||
| 75 | } | ||
| 76 | |||
| 77 | static u32 | ||
| 78 | nvkm_instobj_rd32(struct nvkm_memory *memory, u64 offset) | ||
| 79 | { | ||
| 80 | return ioread32_native(nvkm_instobj(memory)->map + offset); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void | ||
| 84 | nvkm_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) | ||
| 85 | { | ||
| 86 | iowrite32_native(data, nvkm_instobj(memory)->map + offset); | ||
| 87 | } | ||
| 88 | 38 | ||
| 89 | static void | 39 | if (!(map = nvkm_kmap(memory))) { |
| 90 | nvkm_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 | ||
| 96 | static void * | 47 | kvfree(iobj->suspend); |
| 97 | nvkm_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 | ||
| 107 | static const struct nvkm_memory_func | 51 | static int |
| 108 | nvkm_instobj_func = { | 52 | nvkm_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 | |||
| 120 | static void | ||
| 121 | nvkm_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 | ||
| 127 | static void | 59 | iobj->suspend = kvmalloc(size, GFP_KERNEL); |
| 128 | nvkm_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 | ||
| 135 | static void __iomem * | 63 | if (!(map = nvkm_kmap(memory))) { |
| 136 | nvkm_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 | ||
| 145 | static u32 | 73 | void |
| 146 | nvkm_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) | 74 | nvkm_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 | ||
| 152 | static void | 81 | void |
| 153 | nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) | 82 | nvkm_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 | ||
| 159 | static const struct nvkm_memory_func | ||
| 160 | nvkm_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 | |||
| 173 | int | 92 | int |
| 174 | nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, | 93 | nvkm_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 | ||
| 212 | done: | 121 | done: |
| 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 | ||
| 144 | void | ||
| 145 | nvkm_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 | |||
| 235 | static int | 159 | static int |
| 236 | nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend) | 160 | nvkm_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 | ||
| 262 | static int | ||
| 263 | nvkm_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 | ||
| 208 | static int | ||
| 209 | nvkm_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 | |||
| 292 | static void * | 217 | static void * |
| 293 | nvkm_instmem_dtor(struct nvkm_subdev *subdev) | 218 | nvkm_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 | ||
| 52 | struct gk20a_instobj { | 51 | struct 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 | ||
| 121 | static u8 | ||
| 122 | gk20a_instobj_page(struct nvkm_memory *memory) | ||
| 123 | { | ||
| 124 | return 12; | ||
| 125 | } | ||
| 126 | |||
| 122 | static u64 | 127 | static u64 |
| 123 | gk20a_instobj_addr(struct nvkm_memory *memory) | 128 | gk20a_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 | ||
| 128 | static u64 | 133 | static u64 |
| 129 | gk20a_instobj_size(struct nvkm_memory *memory) | 134 | gk20a_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 | ||
| 275 | static void | 280 | static int |
| 276 | gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) | 281 | gk20a_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 | ||
| 283 | static void * | 294 | static 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 | ||
| 296 | out: | 307 | out: |
| 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 | |||
| 342 | gk20a_instobj_func_dma = { | 353 | gk20a_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 | |||
| 355 | gk20a_instobj_func_iommu = { | 365 | gk20a_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 | |||
| 376 | static const struct nvkm_memory_ptrs | ||
| 377 | gk20a_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 | ||
| 367 | static int | 382 | static 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 | ||
| 481 | release_area: | 496 | release_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 | |||
| 554 | gk20a_instmem = { | 564 | gk20a_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 | ||
| 30 | struct nv04_instmem { | 29 | struct 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 | ||
| 40 | struct nv04_instobj { | 39 | struct 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 | ||
| 46 | static enum nvkm_memory_target | 45 | static void |
| 47 | nv04_instobj_target(struct nvkm_memory *memory) | 46 | nv04_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 | ||
| 52 | static u64 | 53 | static u32 |
| 53 | nv04_instobj_addr(struct nvkm_memory *memory) | 54 | nv04_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 | ||
| 58 | static u64 | 61 | static const struct nvkm_memory_ptrs |
| 59 | nv04_instobj_size(struct nvkm_memory *memory) | 62 | nv04_instobj_ptrs = { |
| 63 | .rd32 = nv04_instobj_rd32, | ||
| 64 | .wr32 = nv04_instobj_wr32, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static void | ||
| 68 | nv04_instobj_release(struct nvkm_memory *memory) | ||
| 60 | { | 69 | { |
| 61 | return nv04_instobj(memory)->node->length; | ||
| 62 | } | 70 | } |
| 63 | 71 | ||
| 64 | static void __iomem * | 72 | static 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 | ||
| 72 | static void | 80 | static u64 |
| 73 | nv04_instobj_release(struct nvkm_memory *memory) | 81 | nv04_instobj_size(struct nvkm_memory *memory) |
| 74 | { | 82 | { |
| 83 | return nv04_instobj(memory)->node->length; | ||
| 75 | } | 84 | } |
| 76 | 85 | ||
| 77 | static u32 | 86 | static u64 |
| 78 | nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset) | 87 | nv04_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 | ||
| 85 | static void | 92 | static enum nvkm_memory_target |
| 86 | nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) | 93 | nv04_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 | ||
| 93 | static void * | 98 | static 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 | ||
| 115 | static int | 119 | static 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 * | |||
| 194 | nv04_instmem_dtor(struct nvkm_instmem *base) | 199 | nv04_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 | ||
| 42 | struct nv40_instobj { | 41 | struct 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 | ||
| 48 | static enum nvkm_memory_target | 47 | static void |
| 49 | nv40_instobj_target(struct nvkm_memory *memory) | 48 | nv40_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 | ||
| 54 | static u64 | 54 | static u32 |
| 55 | nv40_instobj_addr(struct nvkm_memory *memory) | 55 | nv40_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 | ||
| 60 | static u64 | 61 | static const struct nvkm_memory_ptrs |
| 61 | nv40_instobj_size(struct nvkm_memory *memory) | 62 | nv40_instobj_ptrs = { |
| 63 | .rd32 = nv40_instobj_rd32, | ||
| 64 | .wr32 = nv40_instobj_wr32, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static void | ||
| 68 | nv40_instobj_release(struct nvkm_memory *memory) | ||
| 62 | { | 69 | { |
| 63 | return nv40_instobj(memory)->node->length; | 70 | wmb(); |
| 64 | } | 71 | } |
| 65 | 72 | ||
| 66 | static void __iomem * | 73 | static 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 | ||
| 73 | static void | 80 | static u64 |
| 74 | nv40_instobj_release(struct nvkm_memory *memory) | 81 | nv40_instobj_size(struct nvkm_memory *memory) |
| 75 | { | 82 | { |
| 83 | return nv40_instobj(memory)->node->length; | ||
| 76 | } | 84 | } |
| 77 | 85 | ||
| 78 | static u32 | 86 | static u64 |
| 79 | nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset) | 87 | nv40_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 | ||
| 85 | static void | 92 | static enum nvkm_memory_target |
| 86 | nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) | 93 | nv40_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 | ||
| 92 | static void * | 98 | static 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 | ||
| 114 | static int | 119 | static 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 * | |||
| 209 | nv40_instmem_dtor(struct nvkm_instmem *base) | 215 | nv40_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 | ||
| 32 | struct nv50_instmem { | 32 | struct 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 | ||
| 44 | struct nv50_instobj { | 45 | struct 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 | ||
| 52 | static enum nvkm_memory_target | 55 | static void |
| 53 | nv50_instobj_target(struct nvkm_memory *memory) | 56 | nv50_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 | ||
| 58 | static u64 | 74 | static u32 |
| 59 | nv50_instobj_addr(struct nvkm_memory *memory) | 75 | nv50_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 | ||
| 64 | static u64 | 95 | static const struct nvkm_memory_ptrs |
| 65 | nv50_instobj_size(struct nvkm_memory *memory) | 96 | nv50_instobj_slow = { |
| 97 | .rd32 = nv50_instobj_rd32_slow, | ||
| 98 | .wr32 = nv50_instobj_wr32_slow, | ||
| 99 | }; | ||
| 100 | |||
| 101 | static void | ||
| 102 | nv50_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 | ||
| 107 | static u32 | ||
| 108 | nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) | ||
| 109 | { | ||
| 110 | return ioread32_native(nv50_instobj(memory)->map + offset); | ||
| 111 | } | ||
| 112 | |||
| 113 | static const struct nvkm_memory_ptrs | ||
| 114 | nv50_instobj_fast = { | ||
| 115 | .rd32 = nv50_instobj_rd32, | ||
| 116 | .wr32 = nv50_instobj_wr32, | ||
| 117 | }; | ||
| 118 | |||
| 70 | static void | 119 | static void |
| 71 | nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) | 120 | nv50_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 | |||
| 182 | static int | ||
| 183 | nv50_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 | ||
| 98 | static void | 190 | static void |
| 99 | nv50_instobj_release(struct nvkm_memory *memory) | 191 | nv50_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 | ||
| 105 | static void __iomem * | 215 | static void __iomem * |
| 106 | nv50_instobj_acquire(struct nvkm_memory *memory) | 216 | nv50_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 | ||
| 124 | static u32 | 236 | /* Attempt to get a direct CPU mapping of the object. */ |
| 125 | nv50_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 | ||
| 142 | static void | 259 | static void |
| 143 | nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) | 260 | nv50_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 | ||
| 158 | static void | 279 | static u64 |
| 159 | nv50_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) | 280 | nv50_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 | |||
| 285 | static u64 | ||
| 286 | nv50_instobj_addr(struct nvkm_memory *memory) | ||
| 287 | { | ||
| 288 | return nvkm_memory_addr(nv50_instobj(memory)->ram); | ||
| 289 | } | ||
| 290 | |||
| 291 | static enum nvkm_memory_target | ||
| 292 | nv50_instobj_target(struct nvkm_memory *memory) | ||
| 293 | { | ||
| 294 | return nvkm_memory_target(nv50_instobj(memory)->ram); | ||
| 163 | } | 295 | } |
| 164 | 296 | ||
| 165 | static void * | 297 | static void * |
| 166 | nv50_instobj_dtor(struct nvkm_memory *memory) | 298 | nv50_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 | |||
| 230 | nv50_instmem = { | 368 | nv50_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 | ||
| 18 | void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *, | 17 | void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *, |
| 19 | int index, struct nvkm_instmem *); | 18 | int index, struct nvkm_instmem *); |
| 19 | void nvkm_instmem_boot(struct nvkm_instmem *); | ||
| 20 | |||
| 21 | #include <core/memory.h> | ||
| 22 | |||
| 23 | struct nvkm_instobj { | ||
| 24 | struct nvkm_memory memory; | ||
| 25 | struct list_head head; | ||
| 26 | u32 *suspend; | ||
| 27 | }; | ||
| 28 | |||
| 29 | void nvkm_instobj_ctor(const struct nvkm_memory_func *func, | ||
| 30 | struct nvkm_instmem *, struct nvkm_instobj *); | ||
| 31 | void 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 | |||
| 28 | int | ||
| 29 | nvkm_ltc_tags_alloc(struct nvkm_ltc *ltc, u32 n, struct nvkm_mm_node **pnode) | ||
| 30 | { | ||
| 31 | int ret = nvkm_mm_head(<c->tags, 0, 1, n, n, 1, pnode); | ||
| 32 | if (ret) | ||
| 33 | *pnode = NULL; | ||
| 34 | return ret; | ||
| 35 | } | ||
| 36 | |||
| 37 | void | ||
| 38 | nvkm_ltc_tags_free(struct nvkm_ltc *ltc, struct nvkm_mm_node **pnode) | ||
| 39 | { | ||
| 40 | nvkm_mm_free(<c->tags, pnode); | ||
| 41 | } | ||
| 42 | 27 | ||
| 43 | void | 28 | void |
| 44 | nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count) | 29 | nvkm_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 * | |||
| 116 | nvkm_ltc_dtor(struct nvkm_subdev *subdev) | 102 | nvkm_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(<c->tag_ram); |
| 120 | nvkm_mm_fini(<c->tags); | ||
| 121 | if (ram) | ||
| 122 | nvkm_mm_free(&ram->vram, <c->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) | |||
| 152 | int | 153 | int |
| 153 | gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) | 154 | gf100_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 | <c->tag_ram); | 190 | true, true, <c->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 | ||
| 199 | mm_init: | 202 | mm_init: |
| 200 | return nvkm_mm_init(<c->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 | ||
| 203 | int | 207 | int |
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(<c->tags, 0, 0, 1); | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static void | 51 | static 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 | |||
| 3 | nvkm-y += nvkm/subdev/mmu/nv41.o | 3 | nvkm-y += nvkm/subdev/mmu/nv41.o |
| 4 | nvkm-y += nvkm/subdev/mmu/nv44.o | 4 | nvkm-y += nvkm/subdev/mmu/nv44.o |
| 5 | nvkm-y += nvkm/subdev/mmu/nv50.o | 5 | nvkm-y += nvkm/subdev/mmu/nv50.o |
| 6 | nvkm-y += nvkm/subdev/mmu/g84.o | ||
| 6 | nvkm-y += nvkm/subdev/mmu/gf100.o | 7 | nvkm-y += nvkm/subdev/mmu/gf100.o |
| 8 | nvkm-y += nvkm/subdev/mmu/gk104.o | ||
| 9 | nvkm-y += nvkm/subdev/mmu/gk20a.o | ||
| 10 | nvkm-y += nvkm/subdev/mmu/gm200.o | ||
| 11 | nvkm-y += nvkm/subdev/mmu/gm20b.o | ||
| 12 | nvkm-y += nvkm/subdev/mmu/gp100.o | ||
| 13 | nvkm-y += nvkm/subdev/mmu/gp10b.o | ||
| 14 | |||
| 15 | nvkm-y += nvkm/subdev/mmu/mem.o | ||
| 16 | nvkm-y += nvkm/subdev/mmu/memnv04.o | ||
| 17 | nvkm-y += nvkm/subdev/mmu/memnv50.o | ||
| 18 | nvkm-y += nvkm/subdev/mmu/memgf100.o | ||
| 19 | |||
| 20 | nvkm-y += nvkm/subdev/mmu/vmm.o | ||
| 21 | nvkm-y += nvkm/subdev/mmu/vmmnv04.o | ||
| 22 | nvkm-y += nvkm/subdev/mmu/vmmnv41.o | ||
| 23 | nvkm-y += nvkm/subdev/mmu/vmmnv44.o | ||
| 24 | nvkm-y += nvkm/subdev/mmu/vmmnv50.o | ||
| 25 | nvkm-y += nvkm/subdev/mmu/vmmgf100.o | ||
| 26 | nvkm-y += nvkm/subdev/mmu/vmmgk104.o | ||
| 27 | nvkm-y += nvkm/subdev/mmu/vmmgk20a.o | ||
| 28 | nvkm-y += nvkm/subdev/mmu/vmmgm200.o | ||
| 29 | nvkm-y += nvkm/subdev/mmu/vmmgm20b.o | ||
| 30 | nvkm-y += nvkm/subdev/mmu/vmmgp100.o | ||
| 31 | nvkm-y += nvkm/subdev/mmu/vmmgp10b.o | ||
| 32 | |||
| 33 | nvkm-y += nvkm/subdev/mmu/umem.o | ||
| 34 | nvkm-y += nvkm/subdev/mmu/ummu.o | ||
| 35 | nvkm-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 | ||
| 29 | void | 30 | #include <nvif/if500d.h> |
| 30 | nvkm_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 | ||
| 74 | static void | 33 | struct nvkm_mmu_ptp { |
| 75 | nvkm_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 | } | ||
| 128 | finish: | ||
| 129 | mmu->func->flush(vm); | ||
| 130 | } | ||
| 131 | 40 | ||
| 132 | static void | 41 | static void |
| 133 | nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length, | 42 | nvkm_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 | ||
| 170 | void | 64 | struct nvkm_mmu_pt * |
| 171 | nvkm_vm_map(struct nvkm_vma *vma, struct nvkm_mem *node) | 65 | nvkm_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 | ||
| 182 | void | 82 | ptp->pt = nvkm_mmu_ptc_get(mmu, 0x1000, 0x1000, false); |
| 183 | nvkm_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 | ||
| 217 | void | 112 | struct nvkm_mmu_ptc { |
| 218 | nvkm_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 | ||
| 223 | static void | 119 | static inline struct nvkm_mmu_ptc * |
| 224 | nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) | 120 | nvkm_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 | ||
| 250 | static int | 140 | void |
| 251 | nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type) | 141 | nvkm_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 | ||
| 276 | int | 166 | struct nvkm_mmu_pt * |
| 277 | nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, | 167 | nvkm_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 | ||
| 324 | void | 219 | void |
| 325 | nvkm_vm_put(struct nvkm_vma *vma) | 220 | nvkm_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 | |||
| 347 | int | ||
| 348 | nvkm_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 | ||
| 365 | int | 233 | static void |
| 366 | nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, | 234 | nvkm_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 | ||
| 404 | int | 245 | static void |
| 405 | nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset, | 246 | nvkm_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 | ||
| 414 | static int | 254 | static void |
| 415 | nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd) | 255 | nvkm_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 | ||
| 438 | static void | 264 | static int |
| 439 | nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd) | 265 | nvkm_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 | ||
| 457 | static void | 277 | static void |
| 458 | nvkm_vm_del(struct kref *kref) | 278 | nvkm_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 | ||
| 472 | int | 314 | static void |
| 473 | nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd) | 315 | nvkm_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 | ||
| 492 | static int | 367 | static int |
| 493 | nvkm_mmu_oneinit(struct nvkm_subdev *subdev) | 368 | nvkm_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 * | |||
| 511 | nvkm_mmu_dtor(struct nvkm_subdev *subdev) | 398 | nvkm_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 | ||
| 537 | int | 427 | int |
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 | |||
| 27 | static const struct nvkm_mmu_func | ||
| 28 | g84_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 | |||
| 37 | int | ||
| 38 | g84_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 | */ |
| 35 | const u8 gf100_pte_storage_type_map[256] = | 32 | const u8 * |
| 36 | { | 33 | gf100_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 | |||
| 72 | static void | ||
| 73 | gf100_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 | |||
| 88 | static inline u64 | ||
| 89 | gf100_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 | |||
| 102 | static void | ||
| 103 | gf100_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 | |||
| 129 | static void | ||
| 130 | gf100_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 | |||
| 148 | static void | ||
| 149 | gf100_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 | |||
| 161 | static void | ||
| 162 | gf100_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 | |||
| 195 | static int | ||
| 196 | gf100_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 | ||
| 202 | static const struct nvkm_mmu_func | 75 | static const struct nvkm_mmu_func |
| 203 | gf100_mmu = { | 76 | gf100_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 | ||
| 217 | int | 85 | int |
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 | |||
| 27 | static const struct nvkm_mmu_func | ||
| 28 | gk104_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 | |||
| 37 | int | ||
| 38 | gk104_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 | |||
| 27 | static const struct nvkm_mmu_func | ||
| 28 | gk20a_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 | |||
| 37 | int | ||
| 38 | gk20a_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 | |||
| 29 | const u8 * | ||
| 30 | gm200_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 | |||
| 71 | static const struct nvkm_mmu_func | ||
| 72 | gm200_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 | |||
| 81 | static const struct nvkm_mmu_func | ||
| 82 | gm200_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 | |||
| 91 | int | ||
| 92 | gm200_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 | |||
| 29 | static const struct nvkm_mmu_func | ||
| 30 | gm20b_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 | |||
| 39 | static const struct nvkm_mmu_func | ||
| 40 | gm20b_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 | |||
| 49 | int | ||
| 50 | gm20b_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 | |||
| 29 | static const struct nvkm_mmu_func | ||
| 30 | gp100_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 | |||
| 39 | int | ||
| 40 | gp100_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 | |||
| 29 | static const struct nvkm_mmu_func | ||
| 30 | gp10b_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 | |||
| 39 | int | ||
| 40 | gp10b_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 | |||
| 30 | struct 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 | |||
| 42 | static enum nvkm_memory_target | ||
| 43 | nvkm_mem_target(struct nvkm_memory *memory) | ||
| 44 | { | ||
| 45 | return nvkm_mem(memory)->target; | ||
| 46 | } | ||
| 47 | |||
| 48 | static u8 | ||
| 49 | nvkm_mem_page(struct nvkm_memory *memory) | ||
| 50 | { | ||
| 51 | return PAGE_SHIFT; | ||
| 52 | } | ||
| 53 | |||
| 54 | static u64 | ||
| 55 | nvkm_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 | |||
| 63 | static u64 | ||
| 64 | nvkm_mem_size(struct nvkm_memory *memory) | ||
| 65 | { | ||
| 66 | return nvkm_mem(memory)->pages << PAGE_SHIFT; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int | ||
| 70 | nvkm_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 | |||
| 82 | static void * | ||
| 83 | nvkm_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 | |||
| 99 | static const struct nvkm_memory_func | ||
| 100 | nvkm_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 | |||
| 109 | static int | ||
| 110 | nvkm_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 | |||
| 122 | static const struct nvkm_memory_func | ||
| 123 | nvkm_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 | |||
| 132 | int | ||
| 133 | nvkm_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 | |||
| 143 | static int | ||
| 144 | nvkm_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 | |||
| 223 | int | ||
| 224 | nvkm_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 | |||
| 5 | int nvkm_mem_new_type(struct nvkm_mmu *, int type, u8 page, u64 size, | ||
| 6 | void *argv, u32 argc, struct nvkm_memory **); | ||
| 7 | int nvkm_mem_map_host(struct nvkm_memory *, void **pmap); | ||
| 8 | |||
| 9 | int nv04_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, | ||
| 10 | struct nvkm_memory **); | ||
| 11 | int nv04_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32, | ||
| 12 | u64 *, u64 *, struct nvkm_vma **); | ||
| 13 | |||
| 14 | int nv50_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, | ||
| 15 | struct nvkm_memory **); | ||
| 16 | int nv50_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32, | ||
| 17 | u64 *, u64 *, struct nvkm_vma **); | ||
| 18 | |||
| 19 | int gf100_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, | ||
| 20 | struct nvkm_memory **); | ||
| 21 | int 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 | |||
| 33 | int | ||
| 34 | gf100_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 | |||
| 68 | int | ||
| 69 | gf100_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 | |||
| 30 | int | ||
| 31 | nv04_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 | |||
| 50 | int | ||
| 51 | nv04_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 | |||
| 33 | int | ||
| 34 | nv50_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 | |||
| 65 | int | ||
| 66 | nv50_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 | |||
| 35 | static void | ||
| 36 | nv04_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 | |||
| 54 | static void | ||
| 55 | nv04_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 | |||
| 66 | static void | ||
| 67 | nv04_vm_flush(struct nvkm_vm *vm) | ||
| 68 | { | ||
| 69 | } | ||
| 70 | |||
| 71 | /******************************************************************************* | ||
| 72 | * MMU subdev | ||
| 73 | ******************************************************************************/ | ||
| 74 | |||
| 75 | static int | ||
| 76 | nv04_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 | |||
| 103 | void * | ||
| 104 | nv04_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 | |||
| 119 | int | ||
| 120 | nv04_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 | ||
| 131 | const struct nvkm_mmu_func | 29 | const struct nvkm_mmu_func |
| 132 | nv04_mmu = { | 30 | nv04_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 | ||
| 145 | int | 37 | int |
| 146 | nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) | 38 | nv04_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 | |||
| 6 | struct nv04_mmu { | ||
| 7 | struct nvkm_mmu base; | ||
| 8 | struct nvkm_vm *vm; | ||
| 9 | dma_addr_t null; | ||
| 10 | void *nullp; | ||
| 11 | }; | ||
| 12 | |||
| 13 | int nv04_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *, | ||
| 14 | int index, struct nvkm_mmu **); | ||
| 15 | void *nv04_mmu_dtor(struct nvkm_mmu *); | ||
| 16 | |||
| 17 | extern 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 | |||
| 37 | static void | ||
| 38 | nv41_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 | |||
| 56 | static void | ||
| 57 | nv41_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 | |||
| 68 | static void | ||
| 69 | nv41_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 | |||
| 88 | static int | ||
| 89 | nv41_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 | ||
| 107 | static void | 31 | static void |
| 108 | nv41_mmu_init(struct nvkm_mmu *base) | 32 | nv41_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 | ||
| 118 | static const struct nvkm_mmu_func | 40 | static const struct nvkm_mmu_func |
| 119 | nv41_mmu = { | 41 | nv41_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 | ||
| 133 | int | 49 | int |
| @@ -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 | |||
| 37 | static void | ||
| 38 | nv44_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 | |||
| 83 | static void | ||
| 84 | nv44_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 | |||
| 116 | static void | ||
| 117 | nv44_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 | |||
| 143 | static void | ||
| 144 | nv44_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 | |||
| 161 | static int | ||
| 162 | nv44_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 | ||
| 188 | static void | 31 | static void |
| 189 | nv44_mmu_init(struct nvkm_mmu *base) | 32 | nv44_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 | ||
| 213 | static const struct nvkm_mmu_func | 55 | static const struct nvkm_mmu_func |
| 214 | nv44_mmu = { | 56 | nv44_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 | ||
| 228 | int | 64 | int |
| @@ -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 | ||
| 31 | static void | 29 | const u8 * |
| 32 | nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2]) | 30 | nv50_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; | |
| 63 | static inline u64 | ||
| 64 | vm_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 | |||
| 76 | static void | ||
| 77 | nv50_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 | |||
| 126 | static void | ||
| 127 | nv50_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 | |||
| 142 | static void | ||
| 143 | nv50_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 | |||
| 155 | static void | ||
| 156 | nv50_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 | |||
| 201 | static int | ||
| 202 | nv50_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 | ||
| 212 | static const struct nvkm_mmu_func | 63 | static const struct nvkm_mmu_func |
| 213 | nv50_mmu = { | 64 | nv50_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 | ||
| 227 | int | 72 | int |
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 | ||
| 11 | struct nvkm_mmu_func { | 11 | struct 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 | |||
| 41 | extern const struct nvkm_mmu_func nv04_mmu; | ||
| 42 | |||
| 43 | const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count); | ||
| 44 | |||
| 45 | const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count); | ||
| 46 | |||
| 47 | const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *); | ||
| 48 | |||
| 49 | struct 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 | ||
| 37 | int nvkm_vm_create(struct nvkm_mmu *, u64, u64, u64, u32, | 61 | void nvkm_mmu_ptc_dump(struct nvkm_mmu *); |
| 38 | struct lock_class_key *, struct nvkm_vm **); | 62 | struct nvkm_mmu_pt * |
| 63 | nvkm_mmu_ptc_get(struct nvkm_mmu *, u32 size, u32 align, bool zero); | ||
| 64 | void 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 | |||
| 33 | static const struct nvkm_object_func nvkm_umem; | ||
| 34 | struct nvkm_memory * | ||
| 35 | nvkm_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 | |||
| 63 | static int | ||
| 64 | nvkm_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 | |||
| 86 | static int | ||
| 87 | nvkm_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 | |||
| 124 | static void * | ||
| 125 | nvkm_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 | |||
| 135 | static const struct nvkm_object_func | ||
| 136 | nvkm_umem = { | ||
| 137 | .dtor = nvkm_umem_dtor, | ||
| 138 | .map = nvkm_umem_map, | ||
| 139 | .unmap = nvkm_umem_unmap, | ||
| 140 | }; | ||
| 141 | |||
| 142 | int | ||
| 143 | nvkm_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 | |||
| 7 | struct 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 | |||
| 24 | int 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 | |||
| 31 | static int | ||
| 32 | nvkm_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 | |||
| 56 | static int | ||
| 57 | nvkm_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 | |||
| 76 | static int | ||
| 77 | nvkm_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 | |||
| 105 | static int | ||
| 106 | nvkm_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 | |||
| 130 | static int | ||
| 131 | nvkm_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 | |||
| 144 | static const struct nvkm_object_func | ||
| 145 | nvkm_ummu = { | ||
| 146 | .mthd = nvkm_ummu_mthd, | ||
| 147 | .sclass = nvkm_ummu_sclass, | ||
| 148 | }; | ||
| 149 | |||
| 150 | int | ||
| 151 | nvkm_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 | |||
| 7 | struct nvkm_ummu { | ||
| 8 | struct nvkm_object object; | ||
| 9 | struct nvkm_mmu *mmu; | ||
| 10 | }; | ||
| 11 | |||
| 12 | int 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 | |||
| 32 | static const struct nvkm_object_func nvkm_uvmm; | ||
| 33 | struct nvkm_vmm * | ||
| 34 | nvkm_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 | |||
| 45 | static int | ||
| 46 | nvkm_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; | ||
| 83 | done: | ||
| 84 | mutex_unlock(&vmm->mutex); | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int | ||
| 89 | nvkm_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); | ||
| 168 | fail: | ||
| 169 | mutex_unlock(&vmm->mutex); | ||
| 170 | nvkm_memory_unref(&memory); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int | ||
| 175 | nvkm_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; | ||
| 207 | done: | ||
| 208 | mutex_unlock(&vmm->mutex); | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int | ||
| 213 | nvkm_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 | |||
| 248 | static int | ||
| 249 | nvkm_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 | |||
| 276 | static int | ||
| 277 | nvkm_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 | |||
| 292 | static void * | ||
| 293 | nvkm_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 | |||
| 300 | static const struct nvkm_object_func | ||
| 301 | nvkm_uvmm = { | ||
| 302 | .dtor = nvkm_uvmm_dtor, | ||
| 303 | .mthd = nvkm_uvmm_mthd, | ||
| 304 | }; | ||
| 305 | |||
| 306 | int | ||
| 307 | nvkm_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 | |||
| 7 | struct nvkm_uvmm { | ||
| 8 | struct nvkm_object object; | ||
| 9 | struct nvkm_vmm *vmm; | ||
| 10 | }; | ||
| 11 | |||
| 12 | int 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 | |||
| 27 | static void | ||
| 28 | nvkm_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 | |||
| 39 | static struct nvkm_vmm_pt * | ||
| 40 | nvkm_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 | |||
| 72 | struct 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 | ||
| 84 | static const char * | ||
| 85 | nvkm_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 | |||
| 97 | static void | ||
| 98 | nvkm_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 | |||
| 119 | static inline void | ||
| 120 | nvkm_vmm_flush_mark(struct nvkm_vmm_iter *it) | ||
| 121 | { | ||
| 122 | it->flush = min(it->flush, it->max - it->lvl); | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline void | ||
| 126 | nvkm_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 | |||
| 137 | static void | ||
| 138 | nvkm_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 | |||
| 196 | static void | ||
| 197 | nvkm_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 | |||
| 257 | static bool | ||
| 258 | nvkm_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 | |||
| 283 | static void | ||
| 284 | nvkm_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 | |||
| 351 | static bool | ||
| 352 | nvkm_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 | |||
| 368 | static void | ||
| 369 | nvkm_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 | |||
| 381 | static bool | ||
| 382 | nvkm_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 | |||
| 393 | static bool | ||
| 394 | nvkm_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 | |||
| 400 | static bool | ||
| 401 | nvkm_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 | |||
| 464 | done: | ||
| 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 | |||
| 471 | static bool | ||
| 472 | nvkm_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 | |||
| 488 | static inline u64 | ||
| 489 | nvkm_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 | |||
| 576 | fail: | ||
| 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 | |||
| 589 | static void | ||
| 590 | nvkm_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 | |||
| 599 | static int | ||
| 600 | nvkm_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 | |||
| 617 | static int | ||
| 618 | nvkm_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 | |||
| 667 | static void | ||
| 668 | nvkm_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 | |||
| 678 | static int | ||
| 679 | nvkm_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 | |||
| 693 | static void | ||
| 694 | nvkm_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 | |||
| 703 | static void | ||
| 704 | nvkm_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 | |||
| 712 | static void | ||
| 713 | nvkm_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 | |||
| 720 | static int | ||
| 721 | nvkm_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 | |||
| 734 | static inline struct nvkm_vma * | ||
| 735 | nvkm_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 | |||
| 747 | struct nvkm_vma * | ||
| 748 | nvkm_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 | |||
| 770 | static void | ||
| 771 | nvkm_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 | |||
| 798 | void | ||
| 799 | nvkm_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 | |||
| 820 | struct nvkm_vma * | ||
| 821 | nvkm_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 | |||
| 837 | static void | ||
| 838 | nvkm_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 | |||
| 875 | int | ||
| 876 | nvkm_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 | |||
| 947 | int | ||
| 948 | nvkm_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 | |||
| 960 | void | ||
| 961 | nvkm_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 | |||
| 990 | void | ||
| 991 | nvkm_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 | |||
| 1005 | void | ||
| 1006 | nvkm_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 | |||
| 1015 | static int | ||
| 1016 | nvkm_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 | |||
| 1051 | static int | ||
| 1052 | nvkm_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 | |||
| 1063 | static int | ||
| 1064 | nvkm_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 | |||
| 1148 | int | ||
| 1149 | nvkm_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 | |||
| 1160 | static void | ||
| 1161 | nvkm_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 | |||
| 1183 | void | ||
| 1184 | nvkm_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 | |||
| 1263 | void | ||
| 1264 | nvkm_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 | |||
| 1275 | int | ||
| 1276 | nvkm_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 | |||
| 1413 | int | ||
| 1414 | nvkm_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 | |||
| 1423 | void | ||
| 1424 | nvkm_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 | |||
| 1433 | int | ||
| 1434 | nvkm_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 | |||
| 1445 | static bool | ||
| 1446 | nvkm_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 | |||
| 1454 | int | ||
| 1455 | nvkm_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 | |||
| 1474 | static void | ||
| 1475 | nvkm_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 | |||
| 1482 | void | ||
| 1483 | nvkm_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 | |||
| 1492 | struct nvkm_vmm * | ||
| 1493 | nvkm_vmm_ref(struct nvkm_vmm *vmm) | ||
| 1494 | { | ||
| 1495 | if (vmm) | ||
| 1496 | kref_get(&vmm->kref); | ||
| 1497 | return vmm; | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | int | ||
| 1501 | nvkm_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> | ||
| 5 | enum nvkm_memory_target; | ||
| 6 | |||
| 7 | struct 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 | |||
| 53 | typedef void (*nvkm_vmm_pxe_func)(struct nvkm_vmm *, | ||
| 54 | struct nvkm_mmu_pt *, u32 ptei, u32 ptes); | ||
| 55 | typedef void (*nvkm_vmm_pde_func)(struct nvkm_vmm *, | ||
| 56 | struct nvkm_vmm_pt *, u32 pdei); | ||
| 57 | typedef void (*nvkm_vmm_pte_func)(struct nvkm_vmm *, struct nvkm_mmu_pt *, | ||
| 58 | u32 ptei, u32 ptes, struct nvkm_vmm_map *); | ||
| 59 | |||
| 60 | struct 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 | |||
| 72 | extern const struct nvkm_vmm_desc_func gf100_vmm_pgd; | ||
| 73 | void gf100_vmm_pgd_pde(struct nvkm_vmm *, struct nvkm_vmm_pt *, u32); | ||
| 74 | extern const struct nvkm_vmm_desc_func gf100_vmm_pgt; | ||
| 75 | void gf100_vmm_pgt_unmap(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32); | ||
| 76 | void gf100_vmm_pgt_mem(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, | ||
| 77 | struct nvkm_vmm_map *); | ||
| 78 | void gf100_vmm_pgt_dma(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, | ||
| 79 | struct nvkm_vmm_map *); | ||
| 80 | void gf100_vmm_pgt_sgl(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, | ||
| 81 | struct nvkm_vmm_map *); | ||
| 82 | |||
| 83 | void gk104_vmm_lpt_invalid(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32); | ||
| 84 | |||
| 85 | struct 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 | |||
| 98 | extern const struct nvkm_vmm_desc gk104_vmm_desc_16_12[]; | ||
| 99 | extern const struct nvkm_vmm_desc gk104_vmm_desc_16_16[]; | ||
| 100 | extern const struct nvkm_vmm_desc gk104_vmm_desc_17_12[]; | ||
| 101 | extern const struct nvkm_vmm_desc gk104_vmm_desc_17_17[]; | ||
| 102 | |||
| 103 | extern const struct nvkm_vmm_desc gm200_vmm_desc_16_12[]; | ||
| 104 | extern const struct nvkm_vmm_desc gm200_vmm_desc_16_16[]; | ||
| 105 | extern const struct nvkm_vmm_desc gm200_vmm_desc_17_12[]; | ||
| 106 | extern const struct nvkm_vmm_desc gm200_vmm_desc_17_17[]; | ||
| 107 | |||
| 108 | extern const struct nvkm_vmm_desc gp100_vmm_desc_12[]; | ||
| 109 | extern const struct nvkm_vmm_desc gp100_vmm_desc_16[]; | ||
| 110 | |||
| 111 | struct 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 | |||
| 132 | struct 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 | |||
| 145 | struct nvkm_vmm_join { | ||
| 146 | struct nvkm_memory *inst; | ||
| 147 | struct list_head head; | ||
| 148 | }; | ||
| 149 | |||
| 150 | int 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 **); | ||
| 153 | int 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 *); | ||
| 156 | struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr); | ||
| 157 | int 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); | ||
| 160 | void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *); | ||
| 161 | void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *); | ||
| 162 | void nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma); | ||
| 163 | |||
| 164 | struct nvkm_vma *nvkm_vma_tail(struct nvkm_vma *, u64 tail); | ||
| 165 | void nvkm_vmm_node_insert(struct nvkm_vmm *, struct nvkm_vma *); | ||
| 166 | |||
| 167 | int 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 **); | ||
| 170 | int nv04_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); | ||
| 171 | |||
| 172 | int 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 **); | ||
| 175 | int gf100_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); | ||
| 176 | int gf100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); | ||
| 177 | void gf100_vmm_part(struct nvkm_vmm *, struct nvkm_memory *); | ||
| 178 | int gf100_vmm_aper(enum nvkm_memory_target); | ||
| 179 | int gf100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); | ||
| 180 | void gf100_vmm_flush_(struct nvkm_vmm *, int); | ||
| 181 | void gf100_vmm_flush(struct nvkm_vmm *, int); | ||
| 182 | |||
| 183 | int gk20a_vmm_aper(enum nvkm_memory_target); | ||
| 184 | |||
| 185 | int 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 **); | ||
| 188 | int gm200_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); | ||
| 189 | int gm200_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); | ||
| 190 | |||
| 191 | int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); | ||
| 192 | int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); | ||
| 193 | void gp100_vmm_flush(struct nvkm_vmm *, int); | ||
| 194 | |||
| 195 | int nv04_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 196 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 197 | int nv41_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 198 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 199 | int nv44_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 200 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 201 | int nv50_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 202 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 203 | int g84_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 204 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 205 | int gf100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 206 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 207 | int gk104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 208 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 209 | int gk20a_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 210 | struct lock_class_key *, const char *, struct nvkm_vmm **); | ||
| 211 | int gm200_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 212 | struct lock_class_key *, const char *, | ||
| 213 | struct nvkm_vmm **); | ||
| 214 | int gm200_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 215 | struct lock_class_key *, const char *, | ||
| 216 | struct nvkm_vmm **); | ||
| 217 | int gm20b_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 218 | struct lock_class_key *, const char *, | ||
| 219 | struct nvkm_vmm **); | ||
| 220 | int gm20b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 221 | struct lock_class_key *, const char *, | ||
| 222 | struct nvkm_vmm **); | ||
| 223 | int gp100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, | ||
| 224 | struct lock_class_key *, const char *, | ||
| 225 | struct nvkm_vmm **); | ||
| 226 | int 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 | |||
| 31 | static inline void | ||
| 32 | gf100_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 | |||
| 57 | void | ||
| 58 | gf100_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 | |||
| 64 | void | ||
| 65 | gf100_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 | |||
| 83 | void | ||
| 84 | gf100_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 | |||
| 90 | void | ||
| 91 | gf100_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 | |||
| 97 | const struct nvkm_vmm_desc_func | ||
| 98 | gf100_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 | |||
| 105 | void | ||
| 106 | gf100_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 | |||
| 146 | const struct nvkm_vmm_desc_func | ||
| 147 | gf100_vmm_pgd = { | ||
| 148 | .unmap = gf100_vmm_pgt_unmap, | ||
| 149 | .pde = gf100_vmm_pgd_pde, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static const struct nvkm_vmm_desc | ||
| 153 | gf100_vmm_desc_17_12[] = { | ||
| 154 | { SPT, 15, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 155 | { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 156 | {} | ||
| 157 | }; | ||
| 158 | |||
| 159 | static const struct nvkm_vmm_desc | ||
| 160 | gf100_vmm_desc_17_17[] = { | ||
| 161 | { LPT, 10, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 162 | { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 163 | {} | ||
| 164 | }; | ||
| 165 | |||
| 166 | static const struct nvkm_vmm_desc | ||
| 167 | gf100_vmm_desc_16_12[] = { | ||
| 168 | { SPT, 14, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 169 | { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 170 | {} | ||
| 171 | }; | ||
| 172 | |||
| 173 | static const struct nvkm_vmm_desc | ||
| 174 | gf100_vmm_desc_16_16[] = { | ||
| 175 | { LPT, 10, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 176 | { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 177 | {} | ||
| 178 | }; | ||
| 179 | |||
| 180 | void | ||
| 181 | gf100_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 | |||
| 211 | void | ||
| 212 | gf100_vmm_flush(struct nvkm_vmm *vmm, int depth) | ||
| 213 | { | ||
| 214 | gf100_vmm_flush_(vmm, 0); | ||
| 215 | } | ||
| 216 | |||
| 217 | int | ||
| 218 | gf100_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 | |||
| 302 | int | ||
| 303 | gf100_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 | |||
| 314 | void | ||
| 315 | gf100_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) | ||
| 316 | { | ||
| 317 | nvkm_fo64(inst, 0x0200, 0x00000000, 2); | ||
| 318 | } | ||
| 319 | |||
| 320 | int | ||
| 321 | gf100_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 | |||
| 344 | int | ||
| 345 | gf100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) | ||
| 346 | { | ||
| 347 | return gf100_vmm_join_(vmm, inst, 0); | ||
| 348 | } | ||
| 349 | |||
| 350 | static const struct nvkm_vmm_func | ||
| 351 | gf100_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 | |||
| 364 | static const struct nvkm_vmm_func | ||
| 365 | gf100_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 | |||
| 378 | int | ||
| 379 | gf100_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 | |||
| 396 | int | ||
| 397 | gf100_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 | |||
| 24 | void | ||
| 25 | gk104_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 | |||
| 32 | static const struct nvkm_vmm_desc_func | ||
| 33 | gk104_vmm_lpt = { | ||
| 34 | .invalid = gk104_vmm_lpt_invalid, | ||
| 35 | .unmap = gf100_vmm_pgt_unmap, | ||
| 36 | .mem = gf100_vmm_pgt_mem, | ||
| 37 | }; | ||
| 38 | |||
| 39 | const struct nvkm_vmm_desc | ||
| 40 | gk104_vmm_desc_17_12[] = { | ||
| 41 | { SPT, 15, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 42 | { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 43 | {} | ||
| 44 | }; | ||
| 45 | |||
| 46 | const struct nvkm_vmm_desc | ||
| 47 | gk104_vmm_desc_17_17[] = { | ||
| 48 | { LPT, 10, 8, 0x1000, &gk104_vmm_lpt }, | ||
| 49 | { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 50 | {} | ||
| 51 | }; | ||
| 52 | |||
| 53 | const struct nvkm_vmm_desc | ||
| 54 | gk104_vmm_desc_16_12[] = { | ||
| 55 | { SPT, 14, 8, 0x1000, &gf100_vmm_pgt }, | ||
| 56 | { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 57 | {} | ||
| 58 | }; | ||
| 59 | |||
| 60 | const struct nvkm_vmm_desc | ||
| 61 | gk104_vmm_desc_16_16[] = { | ||
| 62 | { LPT, 10, 8, 0x1000, &gk104_vmm_lpt }, | ||
| 63 | { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, | ||
| 64 | {} | ||
| 65 | }; | ||
| 66 | |||
| 67 | static const struct nvkm_vmm_func | ||
| 68 | gk104_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 | |||
| 81 | static const struct nvkm_vmm_func | ||
| 82 | gk104_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 | |||
| 95 | int | ||
| 96 | gk104_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 | |||
| 26 | int | ||
| 27 | gk20a_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 | |||
| 36 | static const struct nvkm_vmm_func | ||
| 37 | gk20a_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 | |||
| 50 | static const struct nvkm_vmm_func | ||
| 51 | gk20a_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 | |||
| 64 | int | ||
| 65 | gk20a_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 | |||
| 27 | static void | ||
| 28 | gm200_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 | |||
| 35 | static const struct nvkm_vmm_desc_func | ||
| 36 | gm200_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 | |||
| 44 | static const struct nvkm_vmm_desc_func | ||
| 45 | gm200_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 | |||
| 52 | static void | ||
| 53 | gm200_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 | |||
| 60 | static const struct nvkm_vmm_desc_func | ||
| 61 | gm200_vmm_pgd = { | ||
| 62 | .unmap = gf100_vmm_pgt_unmap, | ||
| 63 | .sparse = gm200_vmm_pgd_sparse, | ||
| 64 | .pde = gf100_vmm_pgd_pde, | ||
| 65 | }; | ||
| 66 | |||
| 67 | const struct nvkm_vmm_desc | ||
| 68 | gm200_vmm_desc_17_12[] = { | ||
| 69 | { SPT, 15, 8, 0x1000, &gm200_vmm_spt }, | ||
| 70 | { PGD, 13, 8, 0x1000, &gm200_vmm_pgd }, | ||
| 71 | {} | ||
| 72 | }; | ||
| 73 | |||
| 74 | const struct nvkm_vmm_desc | ||
| 75 | gm200_vmm_desc_17_17[] = { | ||
| 76 | { LPT, 10, 8, 0x1000, &gm200_vmm_lpt }, | ||
| 77 | { PGD, 13, 8, 0x1000, &gm200_vmm_pgd }, | ||
| 78 | {} | ||
| 79 | }; | ||
| 80 | |||
| 81 | const struct nvkm_vmm_desc | ||
| 82 | gm200_vmm_desc_16_12[] = { | ||
| 83 | { SPT, 14, 8, 0x1000, &gm200_vmm_spt }, | ||
| 84 | { PGD, 14, 8, 0x1000, &gm200_vmm_pgd }, | ||
| 85 | {} | ||
| 86 | }; | ||
| 87 | |||
| 88 | const struct nvkm_vmm_desc | ||
| 89 | gm200_vmm_desc_16_16[] = { | ||
| 90 | { LPT, 10, 8, 0x1000, &gm200_vmm_lpt }, | ||
| 91 | { PGD, 14, 8, 0x1000, &gm200_vmm_pgd }, | ||
| 92 | {} | ||
| 93 | }; | ||
| 94 | |||
| 95 | int | ||
| 96 | gm200_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 | |||
| 103 | int | ||
| 104 | gm200_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) | ||
| 105 | { | ||
| 106 | return gm200_vmm_join_(vmm, inst, 0); | ||
| 107 | } | ||
| 108 | |||
| 109 | static const struct nvkm_vmm_func | ||
| 110 | gm200_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 | |||
| 124 | static const struct nvkm_vmm_func | ||
| 125 | gm200_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 | |||
| 139 | int | ||
| 140 | gm200_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 | |||
| 169 | int | ||
| 170 | gm200_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 | |||
| 178 | int | ||
| 179 | gm200_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 | |||
| 24 | static const struct nvkm_vmm_func | ||
| 25 | gm20b_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 | |||
| 39 | static const struct nvkm_vmm_func | ||
| 40 | gm20b_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 | |||
| 54 | int | ||
| 55 | gm20b_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 | |||
| 63 | int | ||
| 64 | gm20b_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 | |||
| 30 | static inline void | ||
| 31 | gp100_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 | |||
| 44 | static void | ||
| 45 | gp100_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 | |||
| 51 | static void | ||
| 52 | gp100_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 | |||
| 70 | static void | ||
| 71 | gp100_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 | |||
| 77 | static void | ||
| 78 | gp100_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 | |||
| 85 | static const struct nvkm_vmm_desc_func | ||
| 86 | gp100_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 | |||
| 94 | static void | ||
| 95 | gp100_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 | |||
| 102 | static const struct nvkm_vmm_desc_func | ||
| 103 | gp100_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 | |||
| 110 | static inline void | ||
| 111 | gp100_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 | |||
| 124 | static void | ||
| 125 | gp100_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 | |||
| 131 | static inline bool | ||
| 132 | gp100_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 | |||
| 148 | static void | ||
| 149 | gp100_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 | |||
| 165 | static void | ||
| 166 | gp100_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 | |||
| 173 | static void | ||
| 174 | gp100_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 | |||
| 180 | static const struct nvkm_vmm_desc_func | ||
| 181 | gp100_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 | |||
| 188 | static void | ||
| 189 | gp100_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 | |||
| 203 | static const struct nvkm_vmm_desc_func | ||
| 204 | gp100_vmm_desc_pd1 = { | ||
| 205 | .unmap = gf100_vmm_pgt_unmap, | ||
| 206 | .sparse = gp100_vmm_pgt_sparse, | ||
| 207 | .pde = gp100_vmm_pd1_pde, | ||
| 208 | }; | ||
| 209 | |||
| 210 | const struct nvkm_vmm_desc | ||
| 211 | gp100_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 | |||
| 220 | const struct nvkm_vmm_desc | ||
| 221 | gp100_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 | |||
| 230 | int | ||
| 231 | gp100_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 | |||
| 309 | void | ||
| 310 | gp100_vmm_flush(struct nvkm_vmm *vmm, int depth) | ||
| 311 | { | ||
| 312 | gf100_vmm_flush_(vmm, 5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth); | ||
| 313 | } | ||
| 314 | |||
| 315 | int | ||
| 316 | gp100_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 | |||
| 322 | static const struct nvkm_vmm_func | ||
| 323 | gp100_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 | |||
| 340 | int | ||
| 341 | gp100_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 | |||
| 24 | static const struct nvkm_vmm_func | ||
| 25 | gp10b_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 | |||
| 42 | int | ||
| 43 | gp10b_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 | |||
| 27 | static inline void | ||
| 28 | nv04_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 | |||
| 38 | static void | ||
| 39 | nv04_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 | |||
| 45 | static void | ||
| 46 | nv04_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 | |||
| 59 | static void | ||
| 60 | nv04_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 | |||
| 66 | static const struct nvkm_vmm_desc_func | ||
| 67 | nv04_vmm_desc_pgt = { | ||
| 68 | .unmap = nv04_vmm_pgt_unmap, | ||
| 69 | .dma = nv04_vmm_pgt_dma, | ||
| 70 | .sgl = nv04_vmm_pgt_sgl, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static const struct nvkm_vmm_desc | ||
| 74 | nv04_vmm_desc_12[] = { | ||
| 75 | { PGT, 15, 4, 0x1000, &nv04_vmm_desc_pgt }, | ||
| 76 | {} | ||
| 77 | }; | ||
| 78 | |||
| 79 | int | ||
| 80 | nv04_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 | |||
| 92 | static const struct nvkm_vmm_func | ||
| 93 | nv04_vmm = { | ||
| 94 | .valid = nv04_vmm_valid, | ||
| 95 | .page = { | ||
| 96 | { 12, &nv04_vmm_desc_12[0], NVKM_VMM_PAGE_HOST }, | ||
| 97 | {} | ||
| 98 | } | ||
| 99 | }; | ||
| 100 | |||
| 101 | int | ||
| 102 | nv04_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 | |||
| 119 | int | ||
| 120 | nv04_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 | |||
| 26 | static void | ||
| 27 | nv41_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 | |||
| 37 | static void | ||
| 38 | nv41_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 | |||
| 44 | static void | ||
| 45 | nv41_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 | |||
| 60 | static void | ||
| 61 | nv41_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 | |||
| 67 | static const struct nvkm_vmm_desc_func | ||
| 68 | nv41_vmm_desc_pgt = { | ||
| 69 | .unmap = nv41_vmm_pgt_unmap, | ||
| 70 | .dma = nv41_vmm_pgt_dma, | ||
| 71 | .sgl = nv41_vmm_pgt_sgl, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static const struct nvkm_vmm_desc | ||
| 75 | nv41_vmm_desc_12[] = { | ||
| 76 | { PGT, 17, 4, 0x1000, &nv41_vmm_desc_pgt }, | ||
| 77 | {} | ||
| 78 | }; | ||
| 79 | |||
| 80 | static void | ||
| 81 | nv41_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 | |||
| 96 | static const struct nvkm_vmm_func | ||
| 97 | nv41_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 | |||
| 106 | int | ||
| 107 | nv41_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 | |||
| 26 | static void | ||
| 27 | nv44_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 | |||
| 72 | static void | ||
| 73 | nv44_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 | |||
| 104 | static void | ||
| 105 | nv44_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 | |||
| 111 | static void | ||
| 112 | nv44_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 | |||
| 146 | static void | ||
| 147 | nv44_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 | |||
| 171 | static const struct nvkm_vmm_desc_func | ||
| 172 | nv44_vmm_desc_pgt = { | ||
| 173 | .unmap = nv44_vmm_pgt_unmap, | ||
| 174 | .dma = nv44_vmm_pgt_dma, | ||
| 175 | .sgl = nv44_vmm_pgt_sgl, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static const struct nvkm_vmm_desc | ||
| 179 | nv44_vmm_desc_12[] = { | ||
| 180 | { PGT, 17, 4, 0x80000, &nv44_vmm_desc_pgt }, | ||
| 181 | {} | ||
| 182 | }; | ||
| 183 | |||
| 184 | static void | ||
| 185 | nv44_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 | |||
| 197 | static const struct nvkm_vmm_func | ||
| 198 | nv44_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 | |||
| 207 | int | ||
| 208 | nv44_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 | |||
| 31 | static inline void | ||
| 32 | nv50_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 | |||
| 57 | static void | ||
| 58 | nv50_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 | |||
| 64 | static void | ||
| 65 | nv50_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 | |||
| 83 | static void | ||
| 84 | nv50_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 | |||
| 90 | static void | ||
| 91 | nv50_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 | |||
| 97 | static const struct nvkm_vmm_desc_func | ||
| 98 | nv50_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 | |||
| 105 | static bool | ||
| 106 | nv50_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 | |||
| 144 | static void | ||
| 145 | nv50_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 | |||
| 161 | static const struct nvkm_vmm_desc_func | ||
| 162 | nv50_vmm_pgd = { | ||
| 163 | .pde = nv50_vmm_pgd_pde, | ||
| 164 | }; | ||
| 165 | |||
| 166 | static const struct nvkm_vmm_desc | ||
| 167 | nv50_vmm_desc_12[] = { | ||
| 168 | { PGT, 17, 8, 0x1000, &nv50_vmm_pgt }, | ||
| 169 | { PGD, 11, 0, 0x0000, &nv50_vmm_pgd }, | ||
| 170 | {} | ||
| 171 | }; | ||
| 172 | |||
| 173 | static const struct nvkm_vmm_desc | ||
| 174 | nv50_vmm_desc_16[] = { | ||
| 175 | { PGT, 13, 8, 0x1000, &nv50_vmm_pgt }, | ||
| 176 | { PGD, 11, 0, 0x0000, &nv50_vmm_pgd }, | ||
| 177 | {} | ||
| 178 | }; | ||
| 179 | |||
| 180 | static void | ||
| 181 | nv50_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 | |||
| 226 | static int | ||
| 227 | nv50_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 | |||
| 324 | static void | ||
| 325 | nv50_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 | |||
| 338 | static int | ||
| 339 | nv50_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 | |||
| 364 | static const struct nvkm_vmm_func | ||
| 365 | nv50_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 | |||
| 378 | int | ||
| 379 | nv50_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> |
| 28 | struct nvkm_gpuobj; | ||
| 28 | 29 | ||
| 29 | struct nvkm_secboot_func { | 30 | struct 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 | |||
| 12 | nvkm-y += nvkm/subdev/therm/gf119.o | 12 | nvkm-y += nvkm/subdev/therm/gf119.o |
| 13 | nvkm-y += nvkm/subdev/therm/gm107.o | 13 | nvkm-y += nvkm/subdev/therm/gm107.o |
| 14 | nvkm-y += nvkm/subdev/therm/gm200.o | 14 | nvkm-y += nvkm/subdev/therm/gm200.o |
| 15 | nvkm-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 | |||
| 26 | static int | ||
| 27 | gp100_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 | |||
| 45 | static const struct nvkm_therm_func | ||
| 46 | gp100_therm = { | ||
| 47 | .temp_get = gp100_temp_get, | ||
| 48 | .program_alarms = nvkm_therm_program_alarms_polling, | ||
| 49 | }; | ||
| 50 | |||
| 51 | int | ||
| 52 | gp100_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 | } | ||
