aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv04_fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv04_fifo.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fifo.c240
1 files changed, 236 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
index 708293b7ddcd..f89d104698df 100644
--- a/drivers/gpu/drm/nouveau/nv04_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -28,6 +28,7 @@
28#include "drm.h" 28#include "drm.h"
29#include "nouveau_drv.h" 29#include "nouveau_drv.h"
30#include "nouveau_ramht.h" 30#include "nouveau_ramht.h"
31#include "nouveau_util.h"
31 32
32#define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) 33#define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE))
33#define NV04_RAMFC__SIZE 32 34#define NV04_RAMFC__SIZE 32
@@ -128,6 +129,11 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
128 if (ret) 129 if (ret)
129 return ret; 130 return ret;
130 131
132 chan->user = ioremap(pci_resource_start(dev->pdev, 0) +
133 NV03_USER(chan->id), PAGE_SIZE);
134 if (!chan->user)
135 return -ENOMEM;
136
131 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 137 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
132 138
133 /* Setup initial state */ 139 /* Setup initial state */
@@ -151,10 +157,31 @@ void
151nv04_fifo_destroy_context(struct nouveau_channel *chan) 157nv04_fifo_destroy_context(struct nouveau_channel *chan)
152{ 158{
153 struct drm_device *dev = chan->dev; 159 struct drm_device *dev = chan->dev;
160 struct drm_nouveau_private *dev_priv = dev->dev_private;
161 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
162 unsigned long flags;
154 163
155 nv_wr32(dev, NV04_PFIFO_MODE, 164 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
156 nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); 165 pfifo->reassign(dev, false);
157 166
167 /* Unload the context if it's the currently active one */
168 if (pfifo->channel_id(dev) == chan->id) {
169 pfifo->disable(dev);
170 pfifo->unload_context(dev);
171 pfifo->enable(dev);
172 }
173
174 /* Keep it from being rescheduled */
175 nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0);
176
177 pfifo->reassign(dev, true);
178 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
179
180 /* Free the channel resources */
181 if (chan->user) {
182 iounmap(chan->user);
183 chan->user = NULL;
184 }
158 nouveau_gpuobj_ref(NULL, &chan->ramfc); 185 nouveau_gpuobj_ref(NULL, &chan->ramfc);
159} 186}
160 187
@@ -208,7 +235,7 @@ nv04_fifo_unload_context(struct drm_device *dev)
208 if (chid < 0 || chid >= dev_priv->engine.fifo.channels) 235 if (chid < 0 || chid >= dev_priv->engine.fifo.channels)
209 return 0; 236 return 0;
210 237
211 chan = dev_priv->fifos[chid]; 238 chan = dev_priv->channels.ptr[chid];
212 if (!chan) { 239 if (!chan) {
213 NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); 240 NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid);
214 return -EINVAL; 241 return -EINVAL;
@@ -267,6 +294,7 @@ nv04_fifo_init_ramxx(struct drm_device *dev)
267static void 294static void
268nv04_fifo_init_intr(struct drm_device *dev) 295nv04_fifo_init_intr(struct drm_device *dev)
269{ 296{
297 nouveau_irq_register(dev, 8, nv04_fifo_isr);
270 nv_wr32(dev, 0x002100, 0xffffffff); 298 nv_wr32(dev, 0x002100, 0xffffffff);
271 nv_wr32(dev, 0x002140, 0xffffffff); 299 nv_wr32(dev, 0x002140, 0xffffffff);
272} 300}
@@ -289,7 +317,7 @@ nv04_fifo_init(struct drm_device *dev)
289 pfifo->reassign(dev, true); 317 pfifo->reassign(dev, true);
290 318
291 for (i = 0; i < dev_priv->engine.fifo.channels; i++) { 319 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
292 if (dev_priv->fifos[i]) { 320 if (dev_priv->channels.ptr[i]) {
293 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); 321 uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE);
294 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); 322 nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i));
295 } 323 }
@@ -298,3 +326,207 @@ nv04_fifo_init(struct drm_device *dev)
298 return 0; 326 return 0;
299} 327}
300 328
329void
330nv04_fifo_fini(struct drm_device *dev)
331{
332 nv_wr32(dev, 0x2140, 0x00000000);
333 nouveau_irq_unregister(dev, 8);
334}
335
336static bool
337nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
338{
339 struct drm_nouveau_private *dev_priv = dev->dev_private;
340 struct nouveau_channel *chan = NULL;
341 struct nouveau_gpuobj *obj;
342 unsigned long flags;
343 const int subc = (addr >> 13) & 0x7;
344 const int mthd = addr & 0x1ffc;
345 bool handled = false;
346 u32 engine;
347
348 spin_lock_irqsave(&dev_priv->channels.lock, flags);
349 if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels))
350 chan = dev_priv->channels.ptr[chid];
351 if (unlikely(!chan))
352 goto out;
353
354 switch (mthd) {
355 case 0x0000: /* bind object to subchannel */
356 obj = nouveau_ramht_find(chan, data);
357 if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW))
358 break;
359
360 chan->sw_subchannel[subc] = obj->class;
361 engine = 0x0000000f << (subc * 4);
362
363 nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000);
364 handled = true;
365 break;
366 default:
367 engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE);
368 if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
369 break;
370
371 if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc],
372 mthd, data))
373 handled = true;
374 break;
375 }
376
377out:
378 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
379 return handled;
380}
381
382void
383nv04_fifo_isr(struct drm_device *dev)
384{
385 struct drm_nouveau_private *dev_priv = dev->dev_private;
386 struct nouveau_engine *engine = &dev_priv->engine;
387 uint32_t status, reassign;
388 int cnt = 0;
389
390 reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
391 while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
392 uint32_t chid, get;
393
394 nv_wr32(dev, NV03_PFIFO_CACHES, 0);
395
396 chid = engine->fifo.channel_id(dev);
397 get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
398
399 if (status & NV_PFIFO_INTR_CACHE_ERROR) {
400 uint32_t mthd, data;
401 int ptr;
402
403 /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
404 * wrapping on my G80 chips, but CACHE1 isn't big
405 * enough for this much data.. Tests show that it
406 * wraps around to the start at GET=0x800.. No clue
407 * as to why..
408 */
409 ptr = (get & 0x7ff) >> 2;
410
411 if (dev_priv->card_type < NV_40) {
412 mthd = nv_rd32(dev,
413 NV04_PFIFO_CACHE1_METHOD(ptr));
414 data = nv_rd32(dev,
415 NV04_PFIFO_CACHE1_DATA(ptr));
416 } else {
417 mthd = nv_rd32(dev,
418 NV40_PFIFO_CACHE1_METHOD(ptr));
419 data = nv_rd32(dev,
420 NV40_PFIFO_CACHE1_DATA(ptr));
421 }
422
423 if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) {
424 NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
425 "Mthd 0x%04x Data 0x%08x\n",
426 chid, (mthd >> 13) & 7, mthd & 0x1ffc,
427 data);
428 }
429
430 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
431 nv_wr32(dev, NV03_PFIFO_INTR_0,
432 NV_PFIFO_INTR_CACHE_ERROR);
433
434 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
435 nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
436 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
437 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
438 nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
439 nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
440
441 nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
442 nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
443 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
444
445 status &= ~NV_PFIFO_INTR_CACHE_ERROR;
446 }
447
448 if (status & NV_PFIFO_INTR_DMA_PUSHER) {
449 u32 dma_get = nv_rd32(dev, 0x003244);
450 u32 dma_put = nv_rd32(dev, 0x003240);
451 u32 push = nv_rd32(dev, 0x003220);
452 u32 state = nv_rd32(dev, 0x003228);
453
454 if (dev_priv->card_type == NV_50) {
455 u32 ho_get = nv_rd32(dev, 0x003328);
456 u32 ho_put = nv_rd32(dev, 0x003320);
457 u32 ib_get = nv_rd32(dev, 0x003334);
458 u32 ib_put = nv_rd32(dev, 0x003330);
459
460 if (nouveau_ratelimit())
461 NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
462 "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
463 "State 0x%08x Push 0x%08x\n",
464 chid, ho_get, dma_get, ho_put,
465 dma_put, ib_get, ib_put, state,
466 push);
467
468 /* METHOD_COUNT, in DMA_STATE on earlier chipsets */
469 nv_wr32(dev, 0x003364, 0x00000000);
470 if (dma_get != dma_put || ho_get != ho_put) {
471 nv_wr32(dev, 0x003244, dma_put);
472 nv_wr32(dev, 0x003328, ho_put);
473 } else
474 if (ib_get != ib_put) {
475 nv_wr32(dev, 0x003334, ib_put);
476 }
477 } else {
478 NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
479 "Put 0x%08x State 0x%08x Push 0x%08x\n",
480 chid, dma_get, dma_put, state, push);
481
482 if (dma_get != dma_put)
483 nv_wr32(dev, 0x003244, dma_put);
484 }
485
486 nv_wr32(dev, 0x003228, 0x00000000);
487 nv_wr32(dev, 0x003220, 0x00000001);
488 nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
489 status &= ~NV_PFIFO_INTR_DMA_PUSHER;
490 }
491
492 if (status & NV_PFIFO_INTR_SEMAPHORE) {
493 uint32_t sem;
494
495 status &= ~NV_PFIFO_INTR_SEMAPHORE;
496 nv_wr32(dev, NV03_PFIFO_INTR_0,
497 NV_PFIFO_INTR_SEMAPHORE);
498
499 sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
500 nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
501
502 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
503 nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
504 }
505
506 if (dev_priv->card_type == NV_50) {
507 if (status & 0x00000010) {
508 nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
509 status &= ~0x00000010;
510 nv_wr32(dev, 0x002100, 0x00000010);
511 }
512 }
513
514 if (status) {
515 if (nouveau_ratelimit())
516 NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
517 status, chid);
518 nv_wr32(dev, NV03_PFIFO_INTR_0, status);
519 status = 0;
520 }
521
522 nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
523 }
524
525 if (status) {
526 NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
527 nv_wr32(dev, 0x2140, 0);
528 nv_wr32(dev, 0x140, 0);
529 }
530
531 nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
532}