aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvc0_fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvc0_fifo.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c142
1 files changed, 92 insertions, 50 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index 2886f2726a9e..fb4f5943e01b 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -37,7 +37,7 @@ struct nvc0_fifo_priv {
37}; 37};
38 38
39struct nvc0_fifo_chan { 39struct nvc0_fifo_chan {
40 struct nouveau_bo *user; 40 struct nouveau_gpuobj *user;
41 struct nouveau_gpuobj *ramfc; 41 struct nouveau_gpuobj *ramfc;
42}; 42};
43 43
@@ -106,7 +106,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
107 struct nvc0_fifo_priv *priv = pfifo->priv; 107 struct nvc0_fifo_priv *priv = pfifo->priv;
108 struct nvc0_fifo_chan *fifoch; 108 struct nvc0_fifo_chan *fifoch;
109 u64 ib_virt, user_vinst; 109 u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
110 int ret; 110 int ret;
111 111
112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL); 112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL);
@@ -115,28 +115,13 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
115 fifoch = chan->fifo_priv; 115 fifoch = chan->fifo_priv;
116 116
117 /* allocate vram for control regs, map into polling area */ 117 /* allocate vram for control regs, map into polling area */
118 ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, 118 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000,
119 0, 0, &fifoch->user); 119 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->user);
120 if (ret) 120 if (ret)
121 goto error; 121 goto error;
122 122
123 ret = nouveau_bo_pin(fifoch->user, TTM_PL_FLAG_VRAM);
124 if (ret) {
125 nouveau_bo_ref(NULL, &fifoch->user);
126 goto error;
127 }
128
129 user_vinst = fifoch->user->bo.mem.start << PAGE_SHIFT;
130
131 ret = nouveau_bo_map(fifoch->user);
132 if (ret) {
133 nouveau_bo_unpin(fifoch->user);
134 nouveau_bo_ref(NULL, &fifoch->user);
135 goto error;
136 }
137
138 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, 123 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
139 fifoch->user->bo.mem.mm_node); 124 *(struct nouveau_mem **)fifoch->user->node);
140 125
141 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + 126 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) +
142 priv->user_vma.offset + (chan->id * 0x1000), 127 priv->user_vma.offset + (chan->id * 0x1000),
@@ -146,20 +131,6 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
146 goto error; 131 goto error;
147 } 132 }
148 133
149 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
150
151 /* zero channel regs */
152 nouveau_bo_wr32(fifoch->user, 0x0040/4, 0);
153 nouveau_bo_wr32(fifoch->user, 0x0044/4, 0);
154 nouveau_bo_wr32(fifoch->user, 0x0048/4, 0);
155 nouveau_bo_wr32(fifoch->user, 0x004c/4, 0);
156 nouveau_bo_wr32(fifoch->user, 0x0050/4, 0);
157 nouveau_bo_wr32(fifoch->user, 0x0058/4, 0);
158 nouveau_bo_wr32(fifoch->user, 0x005c/4, 0);
159 nouveau_bo_wr32(fifoch->user, 0x0060/4, 0);
160 nouveau_bo_wr32(fifoch->user, 0x0088/4, 0);
161 nouveau_bo_wr32(fifoch->user, 0x008c/4, 0);
162
163 /* ramfc */ 134 /* ramfc */
164 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, 135 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
165 chan->ramin->vinst, 0x100, 136 chan->ramin->vinst, 0x100,
@@ -167,8 +138,8 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
167 if (ret) 138 if (ret)
168 goto error; 139 goto error;
169 140
170 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(user_vinst)); 141 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(fifoch->user->vinst));
171 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(user_vinst)); 142 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(fifoch->user->vinst));
172 nv_wo32(fifoch->ramfc, 0x10, 0x0000face); 143 nv_wo32(fifoch->ramfc, 0x10, 0x0000face);
173 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902); 144 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902);
174 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt)); 145 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt));
@@ -223,11 +194,7 @@ nvc0_fifo_destroy_context(struct nouveau_channel *chan)
223 return; 194 return;
224 195
225 nouveau_gpuobj_ref(NULL, &fifoch->ramfc); 196 nouveau_gpuobj_ref(NULL, &fifoch->ramfc);
226 if (fifoch->user) { 197 nouveau_gpuobj_ref(NULL, &fifoch->user);
227 nouveau_bo_unmap(fifoch->user);
228 nouveau_bo_unpin(fifoch->user);
229 nouveau_bo_ref(NULL, &fifoch->user);
230 }
231 kfree(fifoch); 198 kfree(fifoch);
232} 199}
233 200
@@ -240,6 +207,21 @@ nvc0_fifo_load_context(struct nouveau_channel *chan)
240int 207int
241nvc0_fifo_unload_context(struct drm_device *dev) 208nvc0_fifo_unload_context(struct drm_device *dev)
242{ 209{
210 int i;
211
212 for (i = 0; i < 128; i++) {
213 if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1))
214 continue;
215
216 nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000);
217 nv_wr32(dev, 0x002634, i);
218 if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
219 NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
220 i, nv_rd32(dev, 0x002634));
221 return -EBUSY;
222 }
223 }
224
243 return 0; 225 return 0;
244} 226}
245 227
@@ -309,6 +291,7 @@ nvc0_fifo_init(struct drm_device *dev)
309{ 291{
310 struct drm_nouveau_private *dev_priv = dev->dev_private; 292 struct drm_nouveau_private *dev_priv = dev->dev_private;
311 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 293 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
294 struct nouveau_channel *chan;
312 struct nvc0_fifo_priv *priv; 295 struct nvc0_fifo_priv *priv;
313 int ret, i; 296 int ret, i;
314 297
@@ -351,23 +334,74 @@ nvc0_fifo_init(struct drm_device *dev)
351 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ 334 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
352 nv_wr32(dev, 0x002100, 0xffffffff); 335 nv_wr32(dev, 0x002100, 0xffffffff);
353 nv_wr32(dev, 0x002140, 0xbfffffff); 336 nv_wr32(dev, 0x002140, 0xbfffffff);
337
338 /* restore PFIFO context table */
339 for (i = 0; i < 128; i++) {
340 chan = dev_priv->channels.ptr[i];
341 if (!chan || !chan->fifo_priv)
342 continue;
343
344 nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 |
345 (chan->ramin->vinst >> 12));
346 nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001);
347 }
348 nvc0_fifo_playlist_update(dev);
349
354 return 0; 350 return 0;
355} 351}
356 352
357struct nouveau_enum nvc0_fifo_fault_unit[] = { 353struct nouveau_enum nvc0_fifo_fault_unit[] = {
358 { 0, "PGRAPH" }, 354 { 0x00, "PGRAPH" },
359 { 3, "PEEPHOLE" }, 355 { 0x03, "PEEPHOLE" },
360 { 4, "BAR1" }, 356 { 0x04, "BAR1" },
361 { 5, "BAR3" }, 357 { 0x05, "BAR3" },
362 { 7, "PFIFO" }, 358 { 0x07, "PFIFO" },
359 { 0x10, "PBSP" },
360 { 0x11, "PPPP" },
361 { 0x13, "PCOUNTER" },
362 { 0x14, "PVP" },
363 { 0x15, "PCOPY0" },
364 { 0x16, "PCOPY1" },
365 { 0x17, "PDAEMON" },
363 {} 366 {}
364}; 367};
365 368
366struct nouveau_enum nvc0_fifo_fault_reason[] = { 369struct nouveau_enum nvc0_fifo_fault_reason[] = {
367 { 0, "PT_NOT_PRESENT" }, 370 { 0x00, "PT_NOT_PRESENT" },
368 { 1, "PT_TOO_SHORT" }, 371 { 0x01, "PT_TOO_SHORT" },
369 { 2, "PAGE_NOT_PRESENT" }, 372 { 0x02, "PAGE_NOT_PRESENT" },
370 { 3, "VM_LIMIT_EXCEEDED" }, 373 { 0x03, "VM_LIMIT_EXCEEDED" },
374 { 0x04, "NO_CHANNEL" },
375 { 0x05, "PAGE_SYSTEM_ONLY" },
376 { 0x06, "PAGE_READ_ONLY" },
377 { 0x0a, "COMPRESSED_SYSRAM" },
378 { 0x0c, "INVALID_STORAGE_TYPE" },
379 {}
380};
381
382struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
383 { 0x01, "PCOPY0" },
384 { 0x02, "PCOPY1" },
385 { 0x04, "DISPATCH" },
386 { 0x05, "CTXCTL" },
387 { 0x06, "PFIFO" },
388 { 0x07, "BAR_READ" },
389 { 0x08, "BAR_WRITE" },
390 { 0x0b, "PVP" },
391 { 0x0c, "PPPP" },
392 { 0x0d, "PBSP" },
393 { 0x11, "PCOUNTER" },
394 { 0x12, "PDAEMON" },
395 { 0x14, "CCACHE" },
396 { 0x15, "CCACHE_POST" },
397 {}
398};
399
400struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
401 { 0x01, "TEX" },
402 { 0x0c, "ESETUP" },
403 { 0x0e, "CTXCTL" },
404 { 0x0f, "PROP" },
371 {} 405 {}
372}; 406};
373 407
@@ -385,12 +419,20 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit)
385 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); 419 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10));
386 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); 420 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10));
387 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); 421 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10));
422 u32 client = (stat & 0x00001f00) >> 8;
388 423
389 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", 424 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [",
390 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); 425 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo);
391 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); 426 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
392 printk("] from "); 427 printk("] from ");
393 nouveau_enum_print(nvc0_fifo_fault_unit, unit); 428 nouveau_enum_print(nvc0_fifo_fault_unit, unit);
429 if (stat & 0x00000040) {
430 printk("/");
431 nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
432 } else {
433 printk("/GPC%d/", (stat & 0x1f000000) >> 24);
434 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client);
435 }
394 printk(" on channel 0x%010llx\n", (u64)inst << 12); 436 printk(" on channel 0x%010llx\n", (u64)inst << 12);
395} 437}
396 438