aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_bo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bo.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c193
1 files changed, 145 insertions, 48 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index f6f44779d82..a2908a91495 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -478,10 +478,12 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
478} 478}
479 479
480static inline uint32_t 480static inline uint32_t
481nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, 481nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
482 struct ttm_mem_reg *mem) 482 struct nouveau_channel *chan, struct ttm_mem_reg *mem)
483{ 483{
484 if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) { 484 struct nouveau_bo *nvbo = nouveau_bo(bo);
485
486 if (nvbo->no_vm) {
485 if (mem->mem_type == TTM_PL_TT) 487 if (mem->mem_type == TTM_PL_TT)
486 return NvDmaGART; 488 return NvDmaGART;
487 return NvDmaVRAM; 489 return NvDmaVRAM;
@@ -493,86 +495,181 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan,
493} 495}
494 496
495static int 497static int
496nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, 498nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
497 bool no_wait_reserve, bool no_wait_gpu, 499 struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
498 struct ttm_mem_reg *new_mem)
499{ 500{
500 struct nouveau_bo *nvbo = nouveau_bo(bo);
501 struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); 501 struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
502 struct ttm_mem_reg *old_mem = &bo->mem; 502 struct nouveau_bo *nvbo = nouveau_bo(bo);
503 struct nouveau_channel *chan; 503 u64 length = (new_mem->num_pages << PAGE_SHIFT);
504 uint64_t src_offset, dst_offset; 504 u64 src_offset, dst_offset;
505 uint32_t page_count;
506 int ret; 505 int ret;
507 506
508 chan = nvbo->channel;
509 if (!chan || nvbo->tile_flags || nvbo->no_vm)
510 chan = dev_priv->channel;
511
512 src_offset = old_mem->mm_node->start << PAGE_SHIFT; 507 src_offset = old_mem->mm_node->start << PAGE_SHIFT;
513 dst_offset = new_mem->mm_node->start << PAGE_SHIFT; 508 dst_offset = new_mem->mm_node->start << PAGE_SHIFT;
514 if (chan != dev_priv->channel) { 509 if (!nvbo->no_vm) {
515 if (old_mem->mem_type == TTM_PL_TT) 510 if (old_mem->mem_type == TTM_PL_VRAM)
516 src_offset += dev_priv->vm_gart_base;
517 else
518 src_offset += dev_priv->vm_vram_base; 511 src_offset += dev_priv->vm_vram_base;
519
520 if (new_mem->mem_type == TTM_PL_TT)
521 dst_offset += dev_priv->vm_gart_base;
522 else 512 else
513 src_offset += dev_priv->vm_gart_base;
514
515 if (new_mem->mem_type == TTM_PL_VRAM)
523 dst_offset += dev_priv->vm_vram_base; 516 dst_offset += dev_priv->vm_vram_base;
517 else
518 dst_offset += dev_priv->vm_gart_base;
524 } 519 }
525 520
526 ret = RING_SPACE(chan, 3); 521 ret = RING_SPACE(chan, 3);
527 if (ret) 522 if (ret)
528 return ret; 523 return ret;
529 BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2);
530 OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem));
531 OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem));
532 524
533 if (dev_priv->card_type >= NV_50) { 525 BEGIN_RING(chan, NvSubM2MF, 0x0184, 2);
534 ret = RING_SPACE(chan, 4); 526 OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem));
527 OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem));
528
529 while (length) {
530 u32 amount, stride, height;
531
532 amount = min(length, (u64)(16 * 1024 * 1024));
533 stride = 64 * 4;
534 height = amount / stride;
535
536 if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) {
537 ret = RING_SPACE(chan, 8);
538 if (ret)
539 return ret;
540
541 BEGIN_RING(chan, NvSubM2MF, 0x0200, 7);
542 OUT_RING (chan, 0);
543 OUT_RING (chan, 0x20);
544 OUT_RING (chan, stride);
545 OUT_RING (chan, height);
546 OUT_RING (chan, 1);
547 OUT_RING (chan, 0);
548 OUT_RING (chan, 0);
549 } else {
550 ret = RING_SPACE(chan, 2);
551 if (ret)
552 return ret;
553
554 BEGIN_RING(chan, NvSubM2MF, 0x0200, 1);
555 OUT_RING (chan, 1);
556 }
557 if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) {
558 ret = RING_SPACE(chan, 8);
559 if (ret)
560 return ret;
561
562 BEGIN_RING(chan, NvSubM2MF, 0x021c, 7);
563 OUT_RING (chan, 0);
564 OUT_RING (chan, 0x20);
565 OUT_RING (chan, stride);
566 OUT_RING (chan, height);
567 OUT_RING (chan, 1);
568 OUT_RING (chan, 0);
569 OUT_RING (chan, 0);
570 } else {
571 ret = RING_SPACE(chan, 2);
572 if (ret)
573 return ret;
574
575 BEGIN_RING(chan, NvSubM2MF, 0x021c, 1);
576 OUT_RING (chan, 1);
577 }
578
579 ret = RING_SPACE(chan, 14);
535 if (ret) 580 if (ret)
536 return ret; 581 return ret;
537 BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); 582
538 OUT_RING(chan, 1); 583 BEGIN_RING(chan, NvSubM2MF, 0x0238, 2);
539 BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); 584 OUT_RING (chan, upper_32_bits(src_offset));
540 OUT_RING(chan, 1); 585 OUT_RING (chan, upper_32_bits(dst_offset));
586 BEGIN_RING(chan, NvSubM2MF, 0x030c, 8);
587 OUT_RING (chan, lower_32_bits(src_offset));
588 OUT_RING (chan, lower_32_bits(dst_offset));
589 OUT_RING (chan, stride);
590 OUT_RING (chan, stride);
591 OUT_RING (chan, stride);
592 OUT_RING (chan, height);
593 OUT_RING (chan, 0x00000101);
594 OUT_RING (chan, 0x00000000);
595 BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
596 OUT_RING (chan, 0);
597
598 length -= amount;
599 src_offset += amount;
600 dst_offset += amount;
541 } 601 }
542 602
603 return 0;
604}
605
606static int
607nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
608 struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
609{
610 u32 src_offset = old_mem->mm_node->start << PAGE_SHIFT;
611 u32 dst_offset = new_mem->mm_node->start << PAGE_SHIFT;
612 u32 page_count = new_mem->num_pages;
613 int ret;
614
615 ret = RING_SPACE(chan, 3);
616 if (ret)
617 return ret;
618
619 BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2);
620 OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem));
621 OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem));
622
543 page_count = new_mem->num_pages; 623 page_count = new_mem->num_pages;
544 while (page_count) { 624 while (page_count) {
545 int line_count = (page_count > 2047) ? 2047 : page_count; 625 int line_count = (page_count > 2047) ? 2047 : page_count;
546 626
547 if (dev_priv->card_type >= NV_50) {
548 ret = RING_SPACE(chan, 3);
549 if (ret)
550 return ret;
551 BEGIN_RING(chan, NvSubM2MF, 0x0238, 2);
552 OUT_RING(chan, upper_32_bits(src_offset));
553 OUT_RING(chan, upper_32_bits(dst_offset));
554 }
555 ret = RING_SPACE(chan, 11); 627 ret = RING_SPACE(chan, 11);
556 if (ret) 628 if (ret)
557 return ret; 629 return ret;
630
558 BEGIN_RING(chan, NvSubM2MF, 631 BEGIN_RING(chan, NvSubM2MF,
559 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); 632 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
560 OUT_RING(chan, lower_32_bits(src_offset)); 633 OUT_RING (chan, src_offset);
561 OUT_RING(chan, lower_32_bits(dst_offset)); 634 OUT_RING (chan, dst_offset);
562 OUT_RING(chan, PAGE_SIZE); /* src_pitch */ 635 OUT_RING (chan, PAGE_SIZE); /* src_pitch */
563 OUT_RING(chan, PAGE_SIZE); /* dst_pitch */ 636 OUT_RING (chan, PAGE_SIZE); /* dst_pitch */
564 OUT_RING(chan, PAGE_SIZE); /* line_length */ 637 OUT_RING (chan, PAGE_SIZE); /* line_length */
565 OUT_RING(chan, line_count); 638 OUT_RING (chan, line_count);
566 OUT_RING(chan, (1<<8)|(1<<0)); 639 OUT_RING (chan, 0x00000101);
567 OUT_RING(chan, 0); 640 OUT_RING (chan, 0x00000000);
568 BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); 641 BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
569 OUT_RING(chan, 0); 642 OUT_RING (chan, 0);
570 643
571 page_count -= line_count; 644 page_count -= line_count;
572 src_offset += (PAGE_SIZE * line_count); 645 src_offset += (PAGE_SIZE * line_count);
573 dst_offset += (PAGE_SIZE * line_count); 646 dst_offset += (PAGE_SIZE * line_count);
574 } 647 }
575 648
649 return 0;
650}
651
652static int
653nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
654 bool no_wait_reserve, bool no_wait_gpu,
655 struct ttm_mem_reg *new_mem)
656{
657 struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
658 struct nouveau_bo *nvbo = nouveau_bo(bo);
659 struct nouveau_channel *chan;
660 int ret;
661
662 chan = nvbo->channel;
663 if (!chan || nvbo->no_vm)
664 chan = dev_priv->channel;
665
666 if (dev_priv->card_type < NV_50)
667 ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
668 else
669 ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
670 if (ret)
671 return ret;
672
576 return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); 673 return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem);
577} 674}
578 675