diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 95 |
1 files changed, 27 insertions, 68 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 3bb5ddb4..79fba6ce 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -563,9 +563,11 @@ static int alloc_gmmu_phys_pages(struct vm_gk20a *vm, u32 order, | |||
563 | 563 | ||
564 | gk20a_dbg_fn(""); | 564 | gk20a_dbg_fn(""); |
565 | 565 | ||
566 | /* note: mem_desc slightly abused (wrt. alloc_gmmu_pages) */ | ||
567 | |||
566 | pages = alloc_pages(GFP_KERNEL, order); | 568 | pages = alloc_pages(GFP_KERNEL, order); |
567 | if (!pages) { | 569 | if (!pages) { |
568 | gk20a_dbg(gpu_dbg_pte, "alloc_pages failed\n"); | 570 | gk20a_dbg(gpu_dbg_pte, "alloc_pages failed"); |
569 | goto err_out; | 571 | goto err_out; |
570 | } | 572 | } |
571 | entry->mem.sgt = kzalloc(sizeof(*entry->mem.sgt), GFP_KERNEL); | 573 | entry->mem.sgt = kzalloc(sizeof(*entry->mem.sgt), GFP_KERNEL); |
@@ -575,7 +577,7 @@ static int alloc_gmmu_phys_pages(struct vm_gk20a *vm, u32 order, | |||
575 | } | 577 | } |
576 | err = sg_alloc_table(entry->mem.sgt, 1, GFP_KERNEL); | 578 | err = sg_alloc_table(entry->mem.sgt, 1, GFP_KERNEL); |
577 | if (err) { | 579 | if (err) { |
578 | gk20a_dbg(gpu_dbg_pte, "sg_alloc_table failed\n"); | 580 | gk20a_dbg(gpu_dbg_pte, "sg_alloc_table failed"); |
579 | goto err_sg_table; | 581 | goto err_sg_table; |
580 | } | 582 | } |
581 | sg_set_page(entry->mem.sgt->sgl, pages, len, 0); | 583 | sg_set_page(entry->mem.sgt->sgl, pages, len, 0); |
@@ -598,12 +600,16 @@ static void free_gmmu_phys_pages(struct vm_gk20a *vm, | |||
598 | struct gk20a_mm_entry *entry) | 600 | struct gk20a_mm_entry *entry) |
599 | { | 601 | { |
600 | gk20a_dbg_fn(""); | 602 | gk20a_dbg_fn(""); |
603 | |||
604 | /* note: mem_desc slightly abused (wrt. free_gmmu_pages) */ | ||
605 | |||
601 | free_pages((unsigned long)entry->mem.cpu_va, get_order(entry->mem.size)); | 606 | free_pages((unsigned long)entry->mem.cpu_va, get_order(entry->mem.size)); |
602 | entry->mem.cpu_va = NULL; | 607 | entry->mem.cpu_va = NULL; |
603 | 608 | ||
604 | sg_free_table(entry->mem.sgt); | 609 | sg_free_table(entry->mem.sgt); |
605 | kfree(entry->mem.sgt); | 610 | kfree(entry->mem.sgt); |
606 | entry->mem.sgt = NULL; | 611 | entry->mem.sgt = NULL; |
612 | entry->mem.size = 0; | ||
607 | } | 613 | } |
608 | 614 | ||
609 | static int map_gmmu_phys_pages(struct gk20a_mm_entry *entry) | 615 | static int map_gmmu_phys_pages(struct gk20a_mm_entry *entry) |
@@ -625,83 +631,43 @@ static int alloc_gmmu_pages(struct vm_gk20a *vm, u32 order, | |||
625 | struct gk20a_mm_entry *entry) | 631 | struct gk20a_mm_entry *entry) |
626 | { | 632 | { |
627 | struct device *d = dev_from_vm(vm); | 633 | struct device *d = dev_from_vm(vm); |
634 | struct gk20a *g = gk20a_from_vm(vm); | ||
628 | u32 num_pages = 1 << order; | 635 | u32 num_pages = 1 << order; |
629 | u32 len = num_pages * PAGE_SIZE; | 636 | u32 len = num_pages * PAGE_SIZE; |
630 | dma_addr_t iova; | 637 | int err; |
631 | DEFINE_DMA_ATTRS(attrs); | ||
632 | void *cpuva; | ||
633 | int err = 0; | ||
634 | 638 | ||
635 | gk20a_dbg_fn(""); | 639 | gk20a_dbg_fn(""); |
636 | 640 | ||
637 | if (tegra_platform_is_linsim()) | 641 | if (tegra_platform_is_linsim()) |
638 | return alloc_gmmu_phys_pages(vm, order, entry); | 642 | return alloc_gmmu_phys_pages(vm, order, entry); |
639 | 643 | ||
640 | entry->mem.size = len; | ||
641 | |||
642 | /* | 644 | /* |
643 | * On arm32 we're limited by vmalloc space, so we do not map pages by | 645 | * On arm32 we're limited by vmalloc space, so we do not map pages by |
644 | * default. | 646 | * default. |
645 | */ | 647 | */ |
646 | if (IS_ENABLED(CONFIG_ARM64)) { | 648 | if (IS_ENABLED(CONFIG_ARM64)) |
647 | cpuva = dma_zalloc_coherent(d, len, &iova, GFP_KERNEL); | 649 | err = gk20a_gmmu_alloc(g, len, &entry->mem); |
648 | if (!cpuva) { | 650 | else |
649 | gk20a_err(d, "memory allocation failed\n"); | 651 | err = gk20a_gmmu_alloc_attr(g, DMA_ATTR_NO_KERNEL_MAPPING, |
650 | goto err_out; | 652 | len, &entry->mem); |
651 | } | ||
652 | |||
653 | err = gk20a_get_sgtable(d, &entry->mem.sgt, cpuva, iova, len); | ||
654 | if (err) { | ||
655 | gk20a_err(d, "sgt allocation failed\n"); | ||
656 | goto err_free; | ||
657 | } | ||
658 | |||
659 | entry->mem.cpu_va = cpuva; | ||
660 | } else { | ||
661 | struct page **pages; | ||
662 | |||
663 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); | ||
664 | pages = dma_alloc_attrs(d, len, &iova, GFP_KERNEL, &attrs); | ||
665 | if (!pages) { | ||
666 | gk20a_err(d, "memory allocation failed\n"); | ||
667 | goto err_out; | ||
668 | } | ||
669 | 653 | ||
670 | err = gk20a_get_sgtable_from_pages(d, &entry->mem.sgt, pages, | ||
671 | iova, len); | ||
672 | if (err) { | ||
673 | gk20a_err(d, "sgt allocation failed\n"); | ||
674 | goto err_free; | ||
675 | } | ||
676 | 654 | ||
677 | entry->mem.pages = pages; | 655 | if (err) { |
656 | gk20a_err(d, "memory allocation failed"); | ||
657 | return -ENOMEM; | ||
678 | } | 658 | } |
679 | 659 | ||
680 | return 0; | 660 | return 0; |
681 | |||
682 | err_free: | ||
683 | if (IS_ENABLED(CONFIG_ARM64)) { | ||
684 | dma_free_coherent(d, len, entry->mem.cpu_va, iova); | ||
685 | cpuva = NULL; | ||
686 | } else { | ||
687 | dma_free_attrs(d, len, entry->mem.pages, iova, &attrs); | ||
688 | entry->mem.pages = NULL; | ||
689 | } | ||
690 | iova = 0; | ||
691 | err_out: | ||
692 | return -ENOMEM; | ||
693 | } | 661 | } |
694 | 662 | ||
695 | void free_gmmu_pages(struct vm_gk20a *vm, | 663 | void free_gmmu_pages(struct vm_gk20a *vm, |
696 | struct gk20a_mm_entry *entry) | 664 | struct gk20a_mm_entry *entry) |
697 | { | 665 | { |
698 | struct device *d = dev_from_vm(vm); | 666 | struct gk20a *g = gk20a_from_vm(vm); |
699 | u64 iova; | ||
700 | DEFINE_DMA_ATTRS(attrs); | ||
701 | 667 | ||
702 | gk20a_dbg_fn(""); | 668 | gk20a_dbg_fn(""); |
703 | 669 | ||
704 | if (!entry->mem.sgt) | 670 | if (!entry->mem.size) |
705 | return; | 671 | return; |
706 | 672 | ||
707 | if (tegra_platform_is_linsim()) { | 673 | if (tegra_platform_is_linsim()) { |
@@ -709,24 +675,15 @@ void free_gmmu_pages(struct vm_gk20a *vm, | |||
709 | return; | 675 | return; |
710 | } | 676 | } |
711 | 677 | ||
712 | iova = sg_dma_address(entry->mem.sgt->sgl); | ||
713 | |||
714 | gk20a_free_sgtable(&entry->mem.sgt); | ||
715 | |||
716 | /* | 678 | /* |
717 | * On arm32 we're limited by vmalloc space, so we do not map pages by | 679 | * On arm32 we're limited by vmalloc space, so we do not map pages by |
718 | * default. | 680 | * default. |
719 | */ | 681 | */ |
720 | if (IS_ENABLED(CONFIG_ARM64)) { | 682 | if (IS_ENABLED(CONFIG_ARM64)) |
721 | dma_free_coherent(d, entry->mem.size, entry->mem.cpu_va, iova); | 683 | gk20a_gmmu_free(g, &entry->mem); |
722 | entry->mem.cpu_va = NULL; | 684 | else |
723 | } else { | 685 | gk20a_gmmu_free_attr(g, DMA_ATTR_NO_KERNEL_MAPPING, |
724 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); | 686 | &entry->mem); |
725 | dma_free_attrs(d, entry->mem.size, entry->mem.pages, iova, &attrs); | ||
726 | entry->mem.pages = NULL; | ||
727 | } | ||
728 | entry->mem.size = 0; | ||
729 | entry->mem.sgt = NULL; | ||
730 | } | 687 | } |
731 | 688 | ||
732 | int map_gmmu_pages(struct gk20a_mm_entry *entry) | 689 | int map_gmmu_pages(struct gk20a_mm_entry *entry) |
@@ -2140,6 +2097,8 @@ void gk20a_gmmu_free_attr(struct gk20a *g, enum dma_attr attr, | |||
2140 | 2097 | ||
2141 | if (mem->sgt) | 2098 | if (mem->sgt) |
2142 | gk20a_free_sgtable(&mem->sgt); | 2099 | gk20a_free_sgtable(&mem->sgt); |
2100 | |||
2101 | mem->size = 0; | ||
2143 | } | 2102 | } |
2144 | 2103 | ||
2145 | void gk20a_gmmu_free(struct gk20a *g, struct mem_desc *mem) | 2104 | void gk20a_gmmu_free(struct gk20a *g, struct mem_desc *mem) |