diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_instmem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_instmem.c | 66 |
1 files changed, 24 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 71c01b6e5731..37c7b48ab24a 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
@@ -35,8 +35,6 @@ struct nv50_instmem_priv { | |||
35 | struct nouveau_gpuobj_ref *pramin_pt; | 35 | struct nouveau_gpuobj_ref *pramin_pt; |
36 | struct nouveau_gpuobj_ref *pramin_bar; | 36 | struct nouveau_gpuobj_ref *pramin_bar; |
37 | struct nouveau_gpuobj_ref *fb_bar; | 37 | struct nouveau_gpuobj_ref *fb_bar; |
38 | |||
39 | bool last_access_wr; | ||
40 | }; | 38 | }; |
41 | 39 | ||
42 | #define NV50_INSTMEM_PAGE_SHIFT 12 | 40 | #define NV50_INSTMEM_PAGE_SHIFT 12 |
@@ -147,7 +145,7 @@ nv50_instmem_init(struct drm_device *dev) | |||
147 | if (ret) | 145 | if (ret) |
148 | return ret; | 146 | return ret; |
149 | 147 | ||
150 | if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) | 148 | if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base)) |
151 | return -ENOMEM; | 149 | return -ENOMEM; |
152 | 150 | ||
153 | /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ | 151 | /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ |
@@ -262,23 +260,18 @@ nv50_instmem_init(struct drm_device *dev) | |||
262 | 260 | ||
263 | /* Assume that praying isn't enough, check that we can re-read the | 261 | /* Assume that praying isn't enough, check that we can re-read the |
264 | * entire fake channel back from the PRAMIN BAR */ | 262 | * entire fake channel back from the PRAMIN BAR */ |
265 | dev_priv->engine.instmem.prepare_access(dev, false); | ||
266 | for (i = 0; i < c_size; i += 4) { | 263 | for (i = 0; i < c_size; i += 4) { |
267 | if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { | 264 | if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) { |
268 | NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", | 265 | NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n", |
269 | i); | 266 | i); |
270 | dev_priv->engine.instmem.finish_access(dev); | ||
271 | return -EINVAL; | 267 | return -EINVAL; |
272 | } | 268 | } |
273 | } | 269 | } |
274 | dev_priv->engine.instmem.finish_access(dev); | ||
275 | 270 | ||
276 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); | 271 | nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700); |
277 | 272 | ||
278 | /* Global PRAMIN heap */ | 273 | /* Global PRAMIN heap */ |
279 | if (nouveau_mem_init_heap(&dev_priv->ramin_heap, | 274 | if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) { |
280 | c_size, dev_priv->ramin_size - c_size)) { | ||
281 | dev_priv->ramin_heap = NULL; | ||
282 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | 275 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); |
283 | } | 276 | } |
284 | 277 | ||
@@ -321,7 +314,7 @@ nv50_instmem_takedown(struct drm_device *dev) | |||
321 | nouveau_gpuobj_del(dev, &chan->vm_pd); | 314 | nouveau_gpuobj_del(dev, &chan->vm_pd); |
322 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); | 315 | nouveau_gpuobj_ref_del(dev, &chan->ramfc); |
323 | nouveau_gpuobj_ref_del(dev, &chan->ramin); | 316 | nouveau_gpuobj_ref_del(dev, &chan->ramin); |
324 | nouveau_mem_takedown(&chan->ramin_heap); | 317 | drm_mm_takedown(&chan->ramin_heap); |
325 | 318 | ||
326 | dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; | 319 | dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; |
327 | kfree(chan); | 320 | kfree(chan); |
@@ -436,14 +429,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
436 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | 429 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) |
437 | return -EINVAL; | 430 | return -EINVAL; |
438 | 431 | ||
439 | NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n", | 432 | NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", |
440 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | 433 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); |
441 | 434 | ||
442 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 435 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
443 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 436 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
444 | vram = gpuobj->im_backing_start; | 437 | vram = gpuobj->im_backing_start; |
445 | 438 | ||
446 | NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n", | 439 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", |
447 | gpuobj->im_pramin->start, pte, pte_end); | 440 | gpuobj->im_pramin->start, pte, pte_end); |
448 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | 441 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); |
449 | 442 | ||
@@ -453,27 +446,15 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
453 | vram |= 0x30; | 446 | vram |= 0x30; |
454 | } | 447 | } |
455 | 448 | ||
456 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
457 | while (pte < pte_end) { | 449 | while (pte < pte_end) { |
458 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); | 450 | nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); |
459 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); | 451 | nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); |
460 | vram += NV50_INSTMEM_PAGE_SIZE; | 452 | vram += NV50_INSTMEM_PAGE_SIZE; |
461 | } | 453 | } |
462 | dev_priv->engine.instmem.finish_access(dev); | 454 | dev_priv->engine.instmem.flush(dev); |
463 | |||
464 | nv_wr32(dev, 0x100c80, 0x00040001); | ||
465 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | ||
466 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n"); | ||
467 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
468 | return -EBUSY; | ||
469 | } | ||
470 | 455 | ||
471 | nv_wr32(dev, 0x100c80, 0x00060001); | 456 | nv50_vm_flush(dev, 4); |
472 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { | 457 | nv50_vm_flush(dev, 6); |
473 | NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); | ||
474 | NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); | ||
475 | return -EBUSY; | ||
476 | } | ||
477 | 458 | ||
478 | gpuobj->im_bound = 1; | 459 | gpuobj->im_bound = 1; |
479 | return 0; | 460 | return 0; |
@@ -492,36 +473,37 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
492 | pte = (gpuobj->im_pramin->start >> 12) << 1; | 473 | pte = (gpuobj->im_pramin->start >> 12) << 1; |
493 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; | 474 | pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; |
494 | 475 | ||
495 | dev_priv->engine.instmem.prepare_access(dev, true); | ||
496 | while (pte < pte_end) { | 476 | while (pte < pte_end) { |
497 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 477 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
498 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); | 478 | nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); |
499 | } | 479 | } |
500 | dev_priv->engine.instmem.finish_access(dev); | 480 | dev_priv->engine.instmem.flush(dev); |
501 | 481 | ||
502 | gpuobj->im_bound = 0; | 482 | gpuobj->im_bound = 0; |
503 | return 0; | 483 | return 0; |
504 | } | 484 | } |
505 | 485 | ||
506 | void | 486 | void |
507 | nv50_instmem_prepare_access(struct drm_device *dev, bool write) | 487 | nv50_instmem_flush(struct drm_device *dev) |
508 | { | 488 | { |
509 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 489 | nv_wr32(dev, 0x00330c, 0x00000001); |
510 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 490 | if (!nv_wait(0x00330c, 0x00000002, 0x00000000)) |
511 | 491 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | |
512 | priv->last_access_wr = write; | ||
513 | } | 492 | } |
514 | 493 | ||
515 | void | 494 | void |
516 | nv50_instmem_finish_access(struct drm_device *dev) | 495 | nv84_instmem_flush(struct drm_device *dev) |
517 | { | 496 | { |
518 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 497 | nv_wr32(dev, 0x070000, 0x00000001); |
519 | struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; | 498 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) |
499 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | ||
500 | } | ||
520 | 501 | ||
521 | if (priv->last_access_wr) { | 502 | void |
522 | nv_wr32(dev, 0x070000, 0x00000001); | 503 | nv50_vm_flush(struct drm_device *dev, int engine) |
523 | if (!nv_wait(0x070000, 0x00000001, 0x00000000)) | 504 | { |
524 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | 505 | nv_wr32(dev, 0x100c80, (engine << 16) | 1); |
525 | } | 506 | if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) |
507 | NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); | ||
526 | } | 508 | } |
527 | 509 | ||