aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-09-26 18:55:53 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-02 23:13:17 -0400
commite5f186c4f9812eccbc291da6dfe8b15da546f961 (patch)
tree84e667ebbe00bd91e10cff16defaad95b38d85a9 /drivers
parent8a57d279d6e1bf19d2d2e54f51d4f40c46c7d1a8 (diff)
drm/nv44/vm: fix and enable use of "real" pciegart
Something seems to be missing in regards to flushing specific ranges of the TLB. For the moment, flushing the entire thing seems to make it work alright. Should give 39-bit DMA addressing on the relevant chipsets. v2: allocate contig 16KiB for dummy pages, reported by mwk on irc Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/device/nv40.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c45
4 files changed, 29 insertions, 41 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
index 320ccc4ae05c..18de4c5b202f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
@@ -218,7 +218,7 @@ nv40_identify(struct nouveau_device *device)
218 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 218 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
219 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 219 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
220 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 220 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
221 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 221 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
222 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 222 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
223 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 223 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
224 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 224 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -238,7 +238,7 @@ nv40_identify(struct nouveau_device *device)
238 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 238 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
239 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 239 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
240 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 240 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
241 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 241 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
242 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 242 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
243 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 243 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
244 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 244 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -258,7 +258,7 @@ nv40_identify(struct nouveau_device *device)
258 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 258 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
259 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 259 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
260 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 260 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
261 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 261 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
262 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 262 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
263 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 263 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
264 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 264 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -278,7 +278,7 @@ nv40_identify(struct nouveau_device *device)
278 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 278 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
279 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 279 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
280 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 280 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
281 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 281 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
282 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 282 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
283 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 283 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
284 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 284 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -298,7 +298,7 @@ nv40_identify(struct nouveau_device *device)
298 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 298 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
299 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 299 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
300 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 300 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
301 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 301 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
302 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 302 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
303 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 303 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
304 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 304 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
318 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 318 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
319 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 319 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
320 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 320 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
321 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 321 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
322 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 322 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
323 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 323 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
324 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 324 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -338,7 +338,7 @@ nv40_identify(struct nouveau_device *device)
338 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 338 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
339 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 339 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
340 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 340 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
341 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 341 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
342 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 342 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
343 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 343 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
344 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 344 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
@@ -358,7 +358,7 @@ nv40_identify(struct nouveau_device *device)
358 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 358 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
359 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 359 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass;
360 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; 360 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
361 device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass; 361 device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
362 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; 362 device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
363 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass; 363 device->oclass[NVDEV_ENGINE_FIFO ] = &nv40_fifo_oclass;
364 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass; 364 device->oclass[NVDEV_ENGINE_SW ] = &nv10_software_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
index ad6ad5de51b8..6adbbc9cc361 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.c
@@ -132,10 +132,9 @@ nv04_vmmgr_dtor(struct nouveau_object *object)
132 nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]); 132 nouveau_gpuobj_ref(NULL, &priv->vm->pgt[0].obj[0]);
133 nouveau_vm_ref(NULL, &priv->vm, NULL); 133 nouveau_vm_ref(NULL, &priv->vm, NULL);
134 } 134 }
135 if (priv->page) { 135 if (priv->nullp) {
136 pci_unmap_page(nv_device(priv)->pdev, priv->null, 136 pci_free_consistent(nv_device(priv)->pdev, 16 * 1024,
137 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 137 priv->nullp, priv->null);
138 __free_page(priv->page);
139 } 138 }
140 nouveau_vmmgr_destroy(&priv->base); 139 nouveau_vmmgr_destroy(&priv->base);
141} 140}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
index e21369cd09c0..ec42d4bc86a6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv04.h
@@ -6,8 +6,8 @@
6struct nv04_vmmgr_priv { 6struct nv04_vmmgr_priv {
7 struct nouveau_vmmgr base; 7 struct nouveau_vmmgr base;
8 struct nouveau_vm *vm; 8 struct nouveau_vm *vm;
9 struct page *page;
10 dma_addr_t null; 9 dma_addr_t null;
10 void *nullp;
11}; 11};
12 12
13static inline struct nv04_vmmgr_priv * 13static inline struct nv04_vmmgr_priv *
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
index 8c9cece25e63..0ac18d05a146 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
@@ -23,6 +23,7 @@
23 */ 23 */
24 24
25#include <core/gpuobj.h> 25#include <core/gpuobj.h>
26#include <core/option.h>
26 27
27#include <subdev/timer.h> 28#include <subdev/timer.h>
28#include <subdev/vm.h> 29#include <subdev/vm.h>
@@ -37,16 +38,6 @@
37 ******************************************************************************/ 38 ******************************************************************************/
38 39
39static void 40static void
40nv44_vm_flush_priv(struct nv04_vmmgr_priv *priv, u32 base, u32 size)
41{
42 nv_wr32(priv, 0x100814, (size - 1) << 12);
43 nv_wr32(priv, 0x100808, base | 0x20);
44 if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
45 nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
46 nv_wr32(priv, 0x100808, 0x00000000);
47}
48
49static void
50nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null, 41nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
51 dma_addr_t *list, u32 pte, u32 cnt) 42 dma_addr_t *list, u32 pte, u32 cnt)
52{ 43{
@@ -57,6 +48,7 @@ nv44_vm_fill(struct nouveau_gpuobj *pgt, dma_addr_t null,
57 tmp[1] = nv_ro32(pgt, base + 0x4); 48 tmp[1] = nv_ro32(pgt, base + 0x4);
58 tmp[2] = nv_ro32(pgt, base + 0x8); 49 tmp[2] = nv_ro32(pgt, base + 0x8);
59 tmp[3] = nv_ro32(pgt, base + 0xc); 50 tmp[3] = nv_ro32(pgt, base + 0xc);
51
60 while (cnt--) { 52 while (cnt--) {
61 u32 addr = list ? (*list++ >> 12) : (null >> 12); 53 u32 addr = list ? (*list++ >> 12) : (null >> 12);
62 switch (pte++ & 0x3) { 54 switch (pte++ & 0x3) {
@@ -96,8 +88,6 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
96 struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) 88 struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
97{ 89{
98 struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm; 90 struct nv04_vmmgr_priv *priv = (void *)vma->vm->vmm;
99 u32 base = pte << 12;
100 u32 size = cnt;
101 u32 tmp[4]; 91 u32 tmp[4];
102 int i; 92 int i;
103 93
@@ -122,15 +112,12 @@ nv44_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
122 112
123 if (cnt) 113 if (cnt)
124 nv44_vm_fill(pgt, priv->null, list, pte, cnt); 114 nv44_vm_fill(pgt, priv->null, list, pte, cnt);
125 nv44_vm_flush_priv(priv, base, size);
126} 115}
127 116
128static void 117static void
129nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) 118nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
130{ 119{
131 struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt); 120 struct nv04_vmmgr_priv *priv = (void *)nouveau_vmmgr(pgt);
132 u32 base = pte << 12;
133 u32 size = cnt;
134 121
135 if (pte & 3) { 122 if (pte & 3) {
136 u32 max = 4 - (pte & 3); 123 u32 max = 4 - (pte & 3);
@@ -150,12 +137,17 @@ nv44_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
150 137
151 if (cnt) 138 if (cnt)
152 nv44_vm_fill(pgt, priv->null, NULL, pte, cnt); 139 nv44_vm_fill(pgt, priv->null, NULL, pte, cnt);
153 nv44_vm_flush_priv(priv, base, size);
154} 140}
155 141
156static void 142static void
157nv44_vm_flush(struct nouveau_vm *vm) 143nv44_vm_flush(struct nouveau_vm *vm)
158{ 144{
145 struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
146 nv_wr32(priv, 0x100814, priv->base.limit - NV44_GART_PAGE);
147 nv_wr32(priv, 0x100808, 0x00000020);
148 if (!nv_wait(priv, 0x100808, 0x00000001, 0x00000001))
149 nv_error(priv, "timeout: 0x%08x\n", nv_rd32(priv, 0x100808));
150 nv_wr32(priv, 0x100808, 0x00000000);
159} 151}
160 152
161/******************************************************************************* 153/*******************************************************************************
@@ -171,6 +163,11 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
171 struct nv04_vmmgr_priv *priv; 163 struct nv04_vmmgr_priv *priv;
172 int ret; 164 int ret;
173 165
166 if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
167 return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
168 data, size, pobject);
169 }
170
174 ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART", 171 ret = nouveau_vmmgr_create(parent, engine, oclass, "PCIEGART",
175 "pciegart", &priv); 172 "pciegart", &priv);
176 *pobject = nv_object(priv); 173 *pobject = nv_object(priv);
@@ -187,20 +184,12 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
187 priv->base.unmap = nv44_vm_unmap; 184 priv->base.unmap = nv44_vm_unmap;
188 priv->base.flush = nv44_vm_flush; 185 priv->base.flush = nv44_vm_flush;
189 186
190 priv->page = alloc_page(GFP_DMA32 | GFP_KERNEL); 187 priv->nullp = pci_alloc_consistent(device->pdev, 16 * 1024, &priv->null);
191 if (priv->page) { 188 if (!priv->nullp) {
192 priv->null = pci_map_page(device->pdev, priv->page, 0, 189 nv_error(priv, "unable to allocate dummy pages\n");
193 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 190 return -ENOMEM;
194 if (pci_dma_mapping_error(device->pdev, priv->null)) {
195 __free_page(priv->page);
196 priv->page = NULL;
197 priv->null = 0;
198 }
199 } 191 }
200 192
201 if (!priv->page)
202 nv_warn(priv, "unable to allocate dummy page\n");
203
204 ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096, 193 ret = nouveau_vm_create(&priv->base, 0, NV44_GART_SIZE, 0, 4096,
205 &priv->vm); 194 &priv->vm);
206 if (ret) 195 if (ret)