diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_instmem.c | 258 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_vm.c | 1 |
4 files changed, 162 insertions, 153 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5a71ca4346c8..4d142031d542 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "nouveau_drm.h" | 32 | #include "nouveau_drm.h" |
33 | #include "nouveau_drv.h" | 33 | #include "nouveau_drv.h" |
34 | #include "nouveau_dma.h" | 34 | #include "nouveau_dma.h" |
35 | #include "nouveau_mm.h" | ||
36 | #include "nouveau_vm.h" | ||
35 | 37 | ||
36 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
37 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
@@ -386,10 +388,13 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
386 | man->default_caching = TTM_PL_FLAG_CACHED; | 388 | man->default_caching = TTM_PL_FLAG_CACHED; |
387 | break; | 389 | break; |
388 | case TTM_PL_VRAM: | 390 | case TTM_PL_VRAM: |
389 | if (dev_priv->card_type == NV_50) | 391 | if (dev_priv->card_type == NV_50) { |
390 | man->func = &nouveau_vram_manager; | 392 | man->func = &nouveau_vram_manager; |
391 | else | 393 | man->io_reserve_fastpath = false; |
394 | man->use_io_reserve_lru = true; | ||
395 | } else { | ||
392 | man->func = &ttm_bo_manager_func; | 396 | man->func = &ttm_bo_manager_func; |
397 | } | ||
393 | man->flags = TTM_MEMTYPE_FLAG_FIXED | | 398 | man->flags = TTM_MEMTYPE_FLAG_FIXED | |
394 | TTM_MEMTYPE_FLAG_MAPPABLE; | 399 | TTM_MEMTYPE_FLAG_MAPPABLE; |
395 | man->available_caching = TTM_PL_FLAG_UNCACHED | | 400 | man->available_caching = TTM_PL_FLAG_UNCACHED | |
@@ -858,6 +863,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
858 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | 863 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; |
859 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); | 864 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); |
860 | struct drm_device *dev = dev_priv->dev; | 865 | struct drm_device *dev = dev_priv->dev; |
866 | int ret; | ||
861 | 867 | ||
862 | mem->bus.addr = NULL; | 868 | mem->bus.addr = NULL; |
863 | mem->bus.offset = 0; | 869 | mem->bus.offset = 0; |
@@ -880,9 +886,32 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
880 | #endif | 886 | #endif |
881 | break; | 887 | break; |
882 | case TTM_PL_VRAM: | 888 | case TTM_PL_VRAM: |
883 | mem->bus.offset = mem->start << PAGE_SHIFT; | 889 | { |
890 | struct nouveau_vram *vram = mem->mm_node; | ||
891 | |||
892 | if (!dev_priv->bar1_vm) { | ||
893 | mem->bus.offset = mem->start << PAGE_SHIFT; | ||
894 | mem->bus.base = pci_resource_start(dev->pdev, 1); | ||
895 | mem->bus.is_iomem = true; | ||
896 | break; | ||
897 | } | ||
898 | |||
899 | ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, 12, | ||
900 | NV_MEM_ACCESS_RW, &vram->bar_vma); | ||
901 | if (ret) | ||
902 | return ret; | ||
903 | |||
904 | nouveau_vm_map(&vram->bar_vma, vram); | ||
905 | if (ret) { | ||
906 | nouveau_vm_put(&vram->bar_vma); | ||
907 | return ret; | ||
908 | } | ||
909 | |||
910 | mem->bus.offset = vram->bar_vma.offset; | ||
911 | mem->bus.offset -= 0x0020000000ULL; | ||
884 | mem->bus.base = pci_resource_start(dev->pdev, 1); | 912 | mem->bus.base = pci_resource_start(dev->pdev, 1); |
885 | mem->bus.is_iomem = true; | 913 | mem->bus.is_iomem = true; |
914 | } | ||
886 | break; | 915 | break; |
887 | default: | 916 | default: |
888 | return -EINVAL; | 917 | return -EINVAL; |
@@ -893,6 +922,17 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
893 | static void | 922 | static void |
894 | nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | 923 | nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) |
895 | { | 924 | { |
925 | struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); | ||
926 | struct nouveau_vram *vram = mem->mm_node; | ||
927 | |||
928 | if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) | ||
929 | return; | ||
930 | |||
931 | if (!vram->bar_vma.node) | ||
932 | return; | ||
933 | |||
934 | nouveau_vm_unmap(&vram->bar_vma); | ||
935 | nouveau_vm_put(&vram->bar_vma); | ||
896 | } | 936 | } |
897 | 937 | ||
898 | static int | 938 | static int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index ce1dde4a65d6..452a8652a498 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -55,7 +55,10 @@ struct nouveau_fpriv { | |||
55 | #include "nouveau_reg.h" | 55 | #include "nouveau_reg.h" |
56 | #include "nouveau_bios.h" | 56 | #include "nouveau_bios.h" |
57 | #include "nouveau_util.h" | 57 | #include "nouveau_util.h" |
58 | |||
58 | struct nouveau_grctx; | 59 | struct nouveau_grctx; |
60 | struct nouveau_vram; | ||
61 | #include "nouveau_vm.h" | ||
59 | 62 | ||
60 | #define MAX_NUM_DCB_ENTRIES 16 | 63 | #define MAX_NUM_DCB_ENTRIES 16 |
61 | 64 | ||
@@ -69,6 +72,8 @@ struct nouveau_grctx; | |||
69 | struct nouveau_vram { | 72 | struct nouveau_vram { |
70 | struct drm_device *dev; | 73 | struct drm_device *dev; |
71 | 74 | ||
75 | struct nouveau_vma bar_vma; | ||
76 | |||
72 | struct list_head regions; | 77 | struct list_head regions; |
73 | u32 memtype; | 78 | u32 memtype; |
74 | u64 offset; | 79 | u64 offset; |
@@ -244,6 +249,7 @@ struct nouveau_channel { | |||
244 | void *pgraph_ctx; | 249 | void *pgraph_ctx; |
245 | 250 | ||
246 | /* NV50 VM */ | 251 | /* NV50 VM */ |
252 | struct nouveau_vm *vm; | ||
247 | struct nouveau_gpuobj *vm_pd; | 253 | struct nouveau_gpuobj *vm_pd; |
248 | struct nouveau_gpuobj *vm_gart_pt; | 254 | struct nouveau_gpuobj *vm_gart_pt; |
249 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; | 255 | struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; |
@@ -701,6 +707,10 @@ struct drm_nouveau_private { | |||
701 | uint64_t fb_aper_free; | 707 | uint64_t fb_aper_free; |
702 | int fb_mtrr; | 708 | int fb_mtrr; |
703 | 709 | ||
710 | /* BAR control (NV50-) */ | ||
711 | struct nouveau_vm *bar1_vm; | ||
712 | struct nouveau_vm *bar3_vm; | ||
713 | |||
704 | /* G8x/G9x virtual address space */ | 714 | /* G8x/G9x virtual address space */ |
705 | uint64_t vm_gart_base; | 715 | uint64_t vm_gart_base; |
706 | uint64_t vm_gart_size; | 716 | uint64_t vm_gart_size; |
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 4eb2f0835e27..4ba8f74e77b1 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
@@ -31,12 +31,16 @@ | |||
31 | #include "nouveau_drv.h" | 31 | #include "nouveau_drv.h" |
32 | #include "nouveau_vm.h" | 32 | #include "nouveau_vm.h" |
33 | 33 | ||
34 | #define BAR1_VM_BASE 0x0020000000ULL | ||
35 | #define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) | ||
36 | #define BAR3_VM_BASE 0x0000000000ULL | ||
37 | #define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) | ||
38 | |||
34 | struct nv50_instmem_priv { | 39 | struct nv50_instmem_priv { |
35 | uint32_t save1700[5]; /* 0x1700->0x1710 */ | 40 | uint32_t save1700[5]; /* 0x1700->0x1710 */ |
36 | 41 | ||
37 | struct nouveau_gpuobj *pramin_pt; | 42 | struct nouveau_gpuobj *bar1_dmaobj; |
38 | struct nouveau_gpuobj *pramin_bar; | 43 | struct nouveau_gpuobj *bar3_dmaobj; |
39 | struct nouveau_gpuobj *fb_bar; | ||
40 | }; | 44 | }; |
41 | 45 | ||
42 | static void | 46 | static void |
@@ -50,6 +54,7 @@ nv50_channel_del(struct nouveau_channel **pchan) | |||
50 | return; | 54 | return; |
51 | 55 | ||
52 | nouveau_gpuobj_ref(NULL, &chan->ramfc); | 56 | nouveau_gpuobj_ref(NULL, &chan->ramfc); |
57 | nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); | ||
53 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); | 58 | nouveau_gpuobj_ref(NULL, &chan->vm_pd); |
54 | if (chan->ramin_heap.free_stack.next) | 59 | if (chan->ramin_heap.free_stack.next) |
55 | drm_mm_takedown(&chan->ramin_heap); | 60 | drm_mm_takedown(&chan->ramin_heap); |
@@ -58,14 +63,14 @@ nv50_channel_del(struct nouveau_channel **pchan) | |||
58 | } | 63 | } |
59 | 64 | ||
60 | static int | 65 | static int |
61 | nv50_channel_new(struct drm_device *dev, u32 size, | 66 | nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, |
62 | struct nouveau_channel **pchan) | 67 | struct nouveau_channel **pchan) |
63 | { | 68 | { |
64 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 69 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
65 | u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; | 70 | u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; |
66 | u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; | 71 | u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; |
67 | struct nouveau_channel *chan; | 72 | struct nouveau_channel *chan; |
68 | int ret; | 73 | int ret, i; |
69 | 74 | ||
70 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | 75 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); |
71 | if (!chan) | 76 | if (!chan) |
@@ -94,6 +99,17 @@ nv50_channel_new(struct drm_device *dev, u32 size, | |||
94 | return ret; | 99 | return ret; |
95 | } | 100 | } |
96 | 101 | ||
102 | for (i = 0; i < 0x4000; i += 8) { | ||
103 | nv_wo32(chan->vm_pd, i + 0, 0x00000000); | ||
104 | nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); | ||
105 | } | ||
106 | |||
107 | ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); | ||
108 | if (ret) { | ||
109 | nv50_channel_del(&chan); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
97 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : | 113 | ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : |
98 | chan->ramin->pinst + fc, | 114 | chan->ramin->pinst + fc, |
99 | chan->ramin->vinst + fc, 0x100, | 115 | chan->ramin->vinst + fc, 0x100, |
@@ -113,6 +129,7 @@ nv50_instmem_init(struct drm_device *dev) | |||
113 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 129 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
114 | struct nv50_instmem_priv *priv; | 130 | struct nv50_instmem_priv *priv; |
115 | struct nouveau_channel *chan; | 131 | struct nouveau_channel *chan; |
132 | struct nouveau_vm *vm; | ||
116 | int ret, i; | 133 | int ret, i; |
117 | u32 tmp; | 134 | u32 tmp; |
118 | 135 | ||
@@ -129,53 +146,75 @@ nv50_instmem_init(struct drm_device *dev) | |||
129 | ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); | 146 | ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); |
130 | if (ret) { | 147 | if (ret) { |
131 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | 148 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); |
132 | return -ENOMEM; | 149 | goto error; |
133 | } | 150 | } |
134 | 151 | ||
135 | /* we need a channel to plug into the hw to control the BARs */ | 152 | /* BAR3 */ |
136 | ret = nv50_channel_new(dev, 128*1024, &dev_priv->channels.ptr[0]); | 153 | ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, |
154 | 29, 12, 16, &dev_priv->bar3_vm); | ||
137 | if (ret) | 155 | if (ret) |
138 | return ret; | 156 | goto error; |
139 | chan = dev_priv->channels.ptr[127] = dev_priv->channels.ptr[0]; | ||
140 | 157 | ||
141 | /* allocate page table for PRAMIN BAR */ | 158 | ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, |
142 | ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8, | 159 | 0x1000, NVOBJ_FLAG_DONT_MAP | |
143 | 0x1000, NVOBJ_FLAG_ZERO_ALLOC, | 160 | NVOBJ_FLAG_ZERO_ALLOC, |
144 | &priv->pramin_pt); | 161 | &dev_priv->bar3_vm->pgt[0].obj); |
145 | if (ret) | 162 | if (ret) |
146 | return ret; | 163 | goto error; |
164 | dev_priv->bar3_vm->pgt[0].page_shift = 12; | ||
165 | dev_priv->bar3_vm->pgt[0].refcount = 1; | ||
147 | 166 | ||
148 | nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63); | 167 | nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj); |
149 | nv_wo32(chan->vm_pd, 0x0004, 0); | ||
150 | 168 | ||
151 | /* DMA object for PRAMIN BAR */ | 169 | ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); |
152 | ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar); | ||
153 | if (ret) | 170 | if (ret) |
154 | return ret; | 171 | goto error; |
155 | nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000); | 172 | dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; |
156 | nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1); | ||
157 | nv_wo32(priv->pramin_bar, 0x08, 0x00000000); | ||
158 | nv_wo32(priv->pramin_bar, 0x0c, 0x00000000); | ||
159 | nv_wo32(priv->pramin_bar, 0x10, 0x00000000); | ||
160 | nv_wo32(priv->pramin_bar, 0x14, 0x00000000); | ||
161 | 173 | ||
162 | nv50_instmem_map(chan->ramin); | 174 | ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, |
175 | NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, | ||
176 | NV_MEM_TYPE_VM, NV_MEM_COMP_VM, | ||
177 | &priv->bar3_dmaobj); | ||
178 | if (ret) | ||
179 | goto error; | ||
163 | 180 | ||
164 | /* poke regs... */ | ||
165 | nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); | 181 | nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); |
166 | nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); | 182 | nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); |
167 | nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4)); | 183 | nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); |
168 | 184 | ||
169 | tmp = nv_ri32(dev, 0); | 185 | tmp = nv_ri32(dev, 0); |
170 | nv_wi32(dev, 0, ~tmp); | 186 | nv_wi32(dev, 0, ~tmp); |
171 | if (nv_ri32(dev, 0) != ~tmp) { | 187 | if (nv_ri32(dev, 0) != ~tmp) { |
172 | NV_ERROR(dev, "PRAMIN readback failed\n"); | 188 | NV_ERROR(dev, "PRAMIN readback failed\n"); |
173 | return -EIO; | 189 | ret = -EIO; |
190 | goto error; | ||
174 | } | 191 | } |
175 | nv_wi32(dev, 0, tmp); | 192 | nv_wi32(dev, 0, tmp); |
176 | 193 | ||
177 | dev_priv->ramin_available = true; | 194 | dev_priv->ramin_available = true; |
178 | 195 | ||
196 | /* BAR1 */ | ||
197 | ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, | ||
198 | 29, 12, 16, &vm); | ||
199 | if (ret) | ||
200 | goto error; | ||
201 | |||
202 | ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); | ||
203 | if (ret) | ||
204 | goto error; | ||
205 | nouveau_vm_ref(NULL, &vm, NULL); | ||
206 | |||
207 | ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, | ||
208 | NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, | ||
209 | NV_MEM_TYPE_VM, NV_MEM_COMP_VM, | ||
210 | &priv->bar1_dmaobj); | ||
211 | if (ret) | ||
212 | goto error; | ||
213 | |||
214 | nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); | ||
215 | for (i = 0; i < 8; i++) | ||
216 | nv_wr32(dev, 0x1900 + (i*4), 0); | ||
217 | |||
179 | /* Determine VM layout */ | 218 | /* Determine VM layout */ |
180 | dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); | 219 | dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); |
181 | dev_priv->vm_gart_size = NV50_VM_BLOCK; | 220 | dev_priv->vm_gart_size = NV50_VM_BLOCK; |
@@ -200,38 +239,19 @@ nv50_instmem_init(struct drm_device *dev) | |||
200 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { | 239 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { |
201 | ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, | 240 | ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, |
202 | 0, NVOBJ_FLAG_ZERO_ALLOC, | 241 | 0, NVOBJ_FLAG_ZERO_ALLOC, |
203 | &chan->vm_vram_pt[i]); | 242 | &dev_priv->vm_vram_pt[i]); |
204 | if (ret) { | 243 | if (ret) { |
205 | NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); | 244 | NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); |
206 | dev_priv->vm_vram_pt_nr = i; | 245 | dev_priv->vm_vram_pt_nr = i; |
207 | return ret; | 246 | return ret; |
208 | } | 247 | } |
209 | dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]; | ||
210 | |||
211 | nv_wo32(chan->vm_pd, 0x10 + (i*8), | ||
212 | chan->vm_vram_pt[i]->vinst | 0x61); | ||
213 | nv_wo32(chan->vm_pd, 0x14 + (i*8), 0); | ||
214 | } | 248 | } |
215 | 249 | ||
216 | /* DMA object for FB BAR */ | ||
217 | ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar); | ||
218 | if (ret) | ||
219 | return ret; | ||
220 | nv_wo32(priv->fb_bar, 0x00, 0x7fc00000); | ||
221 | nv_wo32(priv->fb_bar, 0x04, 0x40000000 + | ||
222 | pci_resource_len(dev->pdev, 1) - 1); | ||
223 | nv_wo32(priv->fb_bar, 0x08, 0x40000000); | ||
224 | nv_wo32(priv->fb_bar, 0x0c, 0x00000000); | ||
225 | nv_wo32(priv->fb_bar, 0x10, 0x00000000); | ||
226 | nv_wo32(priv->fb_bar, 0x14, 0x00000000); | ||
227 | |||
228 | dev_priv->engine.instmem.flush(dev); | ||
229 | |||
230 | nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4)); | ||
231 | for (i = 0; i < 8; i++) | ||
232 | nv_wr32(dev, 0x1900 + (i*4), 0); | ||
233 | |||
234 | return 0; | 250 | return 0; |
251 | |||
252 | error: | ||
253 | nv50_instmem_takedown(dev); | ||
254 | return ret; | ||
235 | } | 255 | } |
236 | 256 | ||
237 | void | 257 | void |
@@ -249,23 +269,25 @@ nv50_instmem_takedown(struct drm_device *dev) | |||
249 | 269 | ||
250 | dev_priv->ramin_available = false; | 270 | dev_priv->ramin_available = false; |
251 | 271 | ||
252 | /* Restore state from before init */ | 272 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) |
273 | nouveau_gpuobj_ref(NULL, &dev_priv->vm_vram_pt[i]); | ||
274 | dev_priv->vm_vram_pt_nr = 0; | ||
275 | |||
253 | for (i = 0x1700; i <= 0x1710; i += 4) | 276 | for (i = 0x1700; i <= 0x1710; i += 4) |
254 | nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); | 277 | nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); |
255 | 278 | ||
256 | nouveau_gpuobj_ref(NULL, &priv->fb_bar); | 279 | nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); |
257 | nouveau_gpuobj_ref(NULL, &priv->pramin_bar); | 280 | nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); |
258 | nouveau_gpuobj_ref(NULL, &priv->pramin_pt); | ||
259 | 281 | ||
260 | /* Destroy dummy channel */ | 282 | nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); |
261 | if (chan) { | 283 | dev_priv->channels.ptr[127] = 0; |
262 | for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) | 284 | nv50_channel_del(&dev_priv->channels.ptr[0]); |
263 | nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); | ||
264 | dev_priv->vm_vram_pt_nr = 0; | ||
265 | 285 | ||
266 | nv50_channel_del(&dev_priv->channels.ptr[0]); | 286 | nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj); |
267 | dev_priv->channels.ptr[127] = NULL; | 287 | nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); |
268 | } | 288 | |
289 | if (dev_priv->ramin_heap.free_stack.next) | ||
290 | drm_mm_takedown(&dev_priv->ramin_heap); | ||
269 | 291 | ||
270 | dev_priv->engine.instmem.priv = NULL; | 292 | dev_priv->engine.instmem.priv = NULL; |
271 | kfree(priv); | 293 | kfree(priv); |
@@ -293,9 +315,9 @@ nv50_instmem_resume(struct drm_device *dev) | |||
293 | nv_wr32(dev, NV50_PUNK_UNK1710, 0); | 315 | nv_wr32(dev, NV50_PUNK_UNK1710, 0); |
294 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | | 316 | nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | |
295 | NV50_PUNK_BAR_CFG_BASE_VALID); | 317 | NV50_PUNK_BAR_CFG_BASE_VALID); |
296 | nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) | | 318 | nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | |
297 | NV50_PUNK_BAR1_CTXDMA_VALID); | 319 | NV50_PUNK_BAR1_CTXDMA_VALID); |
298 | nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) | | 320 | nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | |
299 | NV50_PUNK_BAR3_CTXDMA_VALID); | 321 | NV50_PUNK_BAR3_CTXDMA_VALID); |
300 | 322 | ||
301 | for (i = 0; i < 8; i++) | 323 | for (i = 0; i < 8; i++) |
@@ -305,8 +327,7 @@ nv50_instmem_resume(struct drm_device *dev) | |||
305 | } | 327 | } |
306 | 328 | ||
307 | struct nv50_gpuobj_node { | 329 | struct nv50_gpuobj_node { |
308 | struct nouveau_bo *vram; | 330 | struct nouveau_vram *vram; |
309 | struct drm_mm_node *ramin; | ||
310 | u32 align; | 331 | u32 align; |
311 | }; | 332 | }; |
312 | 333 | ||
@@ -323,23 +344,17 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) | |||
323 | return -ENOMEM; | 344 | return -ENOMEM; |
324 | node->align = align; | 345 | node->align = align; |
325 | 346 | ||
326 | ret = nouveau_bo_new(dev, NULL, size, align, TTM_PL_FLAG_VRAM, | 347 | size = (size + 4095) & ~4095; |
327 | 0, 0x0000, true, false, &node->vram); | 348 | align = max(align, (u32)4096); |
328 | if (ret) { | ||
329 | NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); | ||
330 | WARN_ON(1); | ||
331 | return ret; | ||
332 | } | ||
333 | 349 | ||
334 | ret = nouveau_bo_pin(node->vram, TTM_PL_FLAG_VRAM); | 350 | ret = nv50_vram_new(dev, size, align, 0, 0, &node->vram); |
335 | if (ret) { | 351 | if (ret) { |
336 | NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); | 352 | kfree(node); |
337 | nouveau_bo_ref(NULL, &node->vram); | ||
338 | return ret; | 353 | return ret; |
339 | } | 354 | } |
340 | 355 | ||
341 | gpuobj->vinst = node->vram->bo.mem.start << PAGE_SHIFT; | 356 | gpuobj->vinst = node->vram->offset; |
342 | gpuobj->size = node->vram->bo.mem.num_pages << PAGE_SHIFT; | 357 | gpuobj->size = size; |
343 | gpuobj->node = node; | 358 | gpuobj->node = node; |
344 | return 0; | 359 | return 0; |
345 | } | 360 | } |
@@ -347,13 +362,13 @@ nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) | |||
347 | void | 362 | void |
348 | nv50_instmem_put(struct nouveau_gpuobj *gpuobj) | 363 | nv50_instmem_put(struct nouveau_gpuobj *gpuobj) |
349 | { | 364 | { |
365 | struct drm_device *dev = gpuobj->dev; | ||
350 | struct nv50_gpuobj_node *node; | 366 | struct nv50_gpuobj_node *node; |
351 | 367 | ||
352 | node = gpuobj->node; | 368 | node = gpuobj->node; |
353 | gpuobj->node = NULL; | 369 | gpuobj->node = NULL; |
354 | 370 | ||
355 | nouveau_bo_unpin(node->vram); | 371 | nv50_vram_del(dev, &node->vram); |
356 | nouveau_bo_ref(NULL, &node->vram); | ||
357 | kfree(node); | 372 | kfree(node); |
358 | } | 373 | } |
359 | 374 | ||
@@ -361,83 +376,28 @@ int | |||
361 | nv50_instmem_map(struct nouveau_gpuobj *gpuobj) | 376 | nv50_instmem_map(struct nouveau_gpuobj *gpuobj) |
362 | { | 377 | { |
363 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; | 378 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; |
364 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | ||
365 | struct nv50_gpuobj_node *node = gpuobj->node; | 379 | struct nv50_gpuobj_node *node = gpuobj->node; |
366 | struct drm_device *dev = gpuobj->dev; | 380 | int ret; |
367 | struct drm_mm_node *ramin = NULL; | ||
368 | u32 pte, pte_end; | ||
369 | u64 vram; | ||
370 | |||
371 | do { | ||
372 | if (drm_mm_pre_get(&dev_priv->ramin_heap)) | ||
373 | return -ENOMEM; | ||
374 | |||
375 | spin_lock(&dev_priv->ramin_lock); | ||
376 | ramin = drm_mm_search_free(&dev_priv->ramin_heap, gpuobj->size, | ||
377 | node->align, 0); | ||
378 | if (ramin == NULL) { | ||
379 | spin_unlock(&dev_priv->ramin_lock); | ||
380 | return -ENOMEM; | ||
381 | } | ||
382 | |||
383 | ramin = drm_mm_get_block_atomic(ramin, gpuobj->size, node->align); | ||
384 | spin_unlock(&dev_priv->ramin_lock); | ||
385 | } while (ramin == NULL); | ||
386 | |||
387 | pte = (ramin->start >> 12) << 1; | ||
388 | pte_end = ((ramin->size >> 12) << 1) + pte; | ||
389 | vram = gpuobj->vinst; | ||
390 | |||
391 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | ||
392 | ramin->start, pte, pte_end); | ||
393 | NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); | ||
394 | |||
395 | vram |= 1; | ||
396 | if (dev_priv->vram_sys_base) { | ||
397 | vram += dev_priv->vram_sys_base; | ||
398 | vram |= 0x30; | ||
399 | } | ||
400 | |||
401 | while (pte < pte_end) { | ||
402 | nv_wo32(priv->pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); | ||
403 | nv_wo32(priv->pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); | ||
404 | vram += 0x1000; | ||
405 | pte += 2; | ||
406 | } | ||
407 | dev_priv->engine.instmem.flush(dev); | ||
408 | 381 | ||
409 | nv50_vm_flush_engine(dev, 6); | 382 | ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, |
383 | NV_MEM_ACCESS_RW, &node->vram->bar_vma); | ||
384 | if (ret) | ||
385 | return ret; | ||
410 | 386 | ||
411 | node->ramin = ramin; | 387 | nouveau_vm_map(&node->vram->bar_vma, node->vram); |
412 | gpuobj->pinst = ramin->start; | 388 | gpuobj->pinst = node->vram->bar_vma.offset; |
413 | return 0; | 389 | return 0; |
414 | } | 390 | } |
415 | 391 | ||
416 | void | 392 | void |
417 | nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) | 393 | nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) |
418 | { | 394 | { |
419 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; | ||
420 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | ||
421 | struct nv50_gpuobj_node *node = gpuobj->node; | 395 | struct nv50_gpuobj_node *node = gpuobj->node; |
422 | u32 pte, pte_end; | ||
423 | 396 | ||
424 | if (!node->ramin || !dev_priv->ramin_available) | 397 | if (node->vram->bar_vma.node) { |
425 | return; | 398 | nouveau_vm_unmap(&node->vram->bar_vma); |
426 | 399 | nouveau_vm_put(&node->vram->bar_vma); | |
427 | pte = (node->ramin->start >> 12) << 1; | ||
428 | pte_end = ((node->ramin->size >> 12) << 1) + pte; | ||
429 | |||
430 | while (pte < pte_end) { | ||
431 | nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000); | ||
432 | nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000); | ||
433 | pte += 2; | ||
434 | } | 400 | } |
435 | dev_priv->engine.instmem.flush(gpuobj->dev); | ||
436 | |||
437 | spin_lock(&dev_priv->ramin_lock); | ||
438 | drm_mm_put_block(node->ramin); | ||
439 | node->ramin = NULL; | ||
440 | spin_unlock(&dev_priv->ramin_lock); | ||
441 | } | 401 | } |
442 | 402 | ||
443 | void | 403 | void |
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index ab6c3d0ce32e..efc63c0b0d92 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c | |||
@@ -151,7 +151,6 @@ nv50_vm_flush(struct nouveau_vm *vm) | |||
151 | struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; | 151 | struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; |
152 | 152 | ||
153 | pinstmem->flush(vm->dev); | 153 | pinstmem->flush(vm->dev); |
154 | |||
155 | nv50_vm_flush_engine(vm->dev, 6); | 154 | nv50_vm_flush_engine(vm->dev, 6); |
156 | } | 155 | } |
157 | 156 | ||