diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 86 |
1 files changed, 84 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 750ce10c..7b2174bc 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -393,7 +393,7 @@ static int __must_check gk20a_init_system_vm(struct mm_gk20a *mm); | |||
393 | static int __must_check gk20a_init_bar1_vm(struct mm_gk20a *mm); | 393 | static int __must_check gk20a_init_bar1_vm(struct mm_gk20a *mm); |
394 | static int __must_check gk20a_init_hwpm(struct mm_gk20a *mm); | 394 | static int __must_check gk20a_init_hwpm(struct mm_gk20a *mm); |
395 | static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm); | 395 | static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm); |
396 | 396 | static int __must_check gk20a_init_ce_vm(struct mm_gk20a *mm); | |
397 | 397 | ||
398 | struct gk20a_dmabuf_priv { | 398 | struct gk20a_dmabuf_priv { |
399 | struct mutex lock; | 399 | struct mutex lock; |
@@ -702,6 +702,7 @@ void gk20a_remove_vm(struct vm_gk20a *vm, struct mem_desc *inst_block) | |||
702 | static void gk20a_remove_mm_support(struct mm_gk20a *mm) | 702 | static void gk20a_remove_mm_support(struct mm_gk20a *mm) |
703 | { | 703 | { |
704 | struct gk20a *g = gk20a_from_mm(mm); | 704 | struct gk20a *g = gk20a_from_mm(mm); |
705 | struct gk20a_platform *platform = gk20a_get_platform(g->dev); | ||
705 | 706 | ||
706 | if (g->ops.mm.remove_bar2_vm) | 707 | if (g->ops.mm.remove_bar2_vm) |
707 | g->ops.mm.remove_bar2_vm(g); | 708 | g->ops.mm.remove_bar2_vm(g); |
@@ -709,6 +710,14 @@ static void gk20a_remove_mm_support(struct mm_gk20a *mm) | |||
709 | gk20a_remove_vm(&mm->pmu.vm, &mm->pmu.inst_block); | 710 | gk20a_remove_vm(&mm->pmu.vm, &mm->pmu.inst_block); |
710 | gk20a_free_inst_block(gk20a_from_mm(mm), &mm->hwpm.inst_block); | 711 | gk20a_free_inst_block(gk20a_from_mm(mm), &mm->hwpm.inst_block); |
711 | gk20a_vm_remove_support_nofree(&mm->cde.vm); | 712 | gk20a_vm_remove_support_nofree(&mm->cde.vm); |
713 | |||
714 | if (mm->ce_vidmem_ctx_id != ~0) | ||
715 | gk20a_ce_delete_context(g->dev, mm->ce_vidmem_ctx_id ); | ||
716 | |||
717 | mm->ce_vidmem_ctx_id = ~0; | ||
718 | |||
719 | if (platform->has_ce) | ||
720 | gk20a_vm_remove_support_nofree(&mm->ce.vm); | ||
712 | } | 721 | } |
713 | 722 | ||
714 | static int gk20a_alloc_sysmem_flush(struct gk20a *g) | 723 | static int gk20a_alloc_sysmem_flush(struct gk20a *g) |
@@ -754,6 +763,7 @@ int gk20a_init_mm_setup_sw(struct gk20a *g) | |||
754 | { | 763 | { |
755 | struct mm_gk20a *mm = &g->mm; | 764 | struct mm_gk20a *mm = &g->mm; |
756 | int err; | 765 | int err; |
766 | struct gk20a_platform *platform = gk20a_get_platform(g->dev); | ||
757 | 767 | ||
758 | gk20a_dbg_fn(""); | 768 | gk20a_dbg_fn(""); |
759 | 769 | ||
@@ -775,6 +785,8 @@ int gk20a_init_mm_setup_sw(struct gk20a *g) | |||
775 | 785 | ||
776 | gk20a_init_pramin(mm); | 786 | gk20a_init_pramin(mm); |
777 | 787 | ||
788 | mm->ce_vidmem_ctx_id = ~0; | ||
789 | |||
778 | err = gk20a_init_vidmem(mm); | 790 | err = gk20a_init_vidmem(mm); |
779 | if (err) | 791 | if (err) |
780 | return err; | 792 | return err; |
@@ -804,6 +816,12 @@ int gk20a_init_mm_setup_sw(struct gk20a *g) | |||
804 | if (err) | 816 | if (err) |
805 | return err; | 817 | return err; |
806 | 818 | ||
819 | if (platform->has_ce) { | ||
820 | err = gk20a_init_ce_vm(mm); | ||
821 | if (err) | ||
822 | return err; | ||
823 | } | ||
824 | |||
807 | /* set vm_alloc_share op here as gk20a_as_alloc_share needs it */ | 825 | /* set vm_alloc_share op here as gk20a_as_alloc_share needs it */ |
808 | g->ops.mm.vm_alloc_share = gk20a_vm_alloc_share; | 826 | g->ops.mm.vm_alloc_share = gk20a_vm_alloc_share; |
809 | mm->remove_support = gk20a_remove_mm_support; | 827 | mm->remove_support = gk20a_remove_mm_support; |
@@ -881,6 +899,25 @@ int gk20a_init_mm_support(struct gk20a *g) | |||
881 | return err; | 899 | return err; |
882 | } | 900 | } |
883 | 901 | ||
902 | void gk20a_init_mm_ce_context(struct gk20a *g) | ||
903 | { | ||
904 | #if defined(CONFIG_GK20A_VIDMEM) | ||
905 | if (g->mm.vidmem_size && (g->mm.ce_vidmem_ctx_id == ~0)) { | ||
906 | g->mm.ce_vidmem_ctx_id = | ||
907 | gk20a_ce_create_context_with_cb(g->dev, | ||
908 | gk20a_fifo_get_fast_ce_runlist_id(g), | ||
909 | -1, | ||
910 | -1, | ||
911 | -1, | ||
912 | NULL); | ||
913 | |||
914 | if (g->mm.ce_vidmem_ctx_id == ~0) | ||
915 | gk20a_err(g->dev, | ||
916 | "Failed to allocate CE context for vidmem page clearing support"); | ||
917 | } | ||
918 | #endif | ||
919 | } | ||
920 | |||
884 | static int alloc_gmmu_phys_pages(struct vm_gk20a *vm, u32 order, | 921 | static int alloc_gmmu_phys_pages(struct vm_gk20a *vm, u32 order, |
885 | struct gk20a_mm_entry *entry) | 922 | struct gk20a_mm_entry *entry) |
886 | { | 923 | { |
@@ -2484,6 +2521,7 @@ int gk20a_gmmu_alloc_attr_vid_at(struct gk20a *g, enum dma_attr attr, | |||
2484 | struct device *d = &g->mm.vidmem_dev; | 2521 | struct device *d = &g->mm.vidmem_dev; |
2485 | int err; | 2522 | int err; |
2486 | dma_addr_t iova; | 2523 | dma_addr_t iova; |
2524 | bool need_pramin_access = true; | ||
2487 | DEFINE_DMA_ATTRS(attrs); | 2525 | DEFINE_DMA_ATTRS(attrs); |
2488 | 2526 | ||
2489 | gk20a_dbg_fn(""); | 2527 | gk20a_dbg_fn(""); |
@@ -2519,7 +2557,38 @@ int gk20a_gmmu_alloc_attr_vid_at(struct gk20a *g, enum dma_attr attr, | |||
2519 | mem->size = size; | 2557 | mem->size = size; |
2520 | mem->aperture = APERTURE_VIDMEM; | 2558 | mem->aperture = APERTURE_VIDMEM; |
2521 | 2559 | ||
2522 | gk20a_memset(g, mem, 0, 0, size); | 2560 | if (g->mm.ce_vidmem_ctx_id != ~0) { |
2561 | struct gk20a_fence *gk20a_fence_out = NULL; | ||
2562 | u64 dst_bufbase = g->ops.mm.get_iova_addr(g, mem->sgt->sgl, 0); | ||
2563 | |||
2564 | err = gk20a_ce_execute_ops(g->dev, | ||
2565 | g->mm.ce_vidmem_ctx_id, | ||
2566 | 0, | ||
2567 | dst_bufbase, | ||
2568 | (u64)size, | ||
2569 | 0x00000000, | ||
2570 | NVGPU_CE_DST_LOCATION_LOCAL_FB, | ||
2571 | NVGPU_CE_MEMSET, | ||
2572 | NULL, | ||
2573 | 0, | ||
2574 | &gk20a_fence_out); | ||
2575 | |||
2576 | if (!err) { | ||
2577 | if (gk20a_fence_out) { | ||
2578 | err = gk20a_fence_wait(gk20a_fence_out, gk20a_get_gr_idle_timeout(g)); | ||
2579 | gk20a_fence_put(gk20a_fence_out); | ||
2580 | if (err) | ||
2581 | gk20a_err(g->dev, | ||
2582 | "Failed to get the fence_out from CE execute ops"); | ||
2583 | else | ||
2584 | need_pramin_access = false; | ||
2585 | } | ||
2586 | } else | ||
2587 | gk20a_err(g->dev, "Failed gk20a_ce_execute_ops[%d]",err); | ||
2588 | } | ||
2589 | |||
2590 | if (need_pramin_access) | ||
2591 | gk20a_memset(g, mem, 0, 0, size); | ||
2523 | 2592 | ||
2524 | gk20a_dbg_fn("done"); | 2593 | gk20a_dbg_fn("done"); |
2525 | 2594 | ||
@@ -4125,6 +4194,19 @@ static int gk20a_init_cde_vm(struct mm_gk20a *mm) | |||
4125 | false, false, "cde"); | 4194 | false, false, "cde"); |
4126 | } | 4195 | } |
4127 | 4196 | ||
4197 | static int gk20a_init_ce_vm(struct mm_gk20a *mm) | ||
4198 | { | ||
4199 | struct vm_gk20a *vm = &mm->ce.vm; | ||
4200 | struct gk20a *g = gk20a_from_mm(mm); | ||
4201 | u32 big_page_size = gk20a_get_platform(g->dev)->default_big_page_size; | ||
4202 | |||
4203 | return gk20a_init_vm(mm, vm, big_page_size, | ||
4204 | SZ_4K * 16, | ||
4205 | NV_MM_DEFAULT_KERNEL_SIZE, | ||
4206 | NV_MM_DEFAULT_KERNEL_SIZE + NV_MM_DEFAULT_USER_SIZE, | ||
4207 | false, false, "ce"); | ||
4208 | } | ||
4209 | |||
4128 | void gk20a_mm_init_pdb(struct gk20a *g, struct mem_desc *inst_block, | 4210 | void gk20a_mm_init_pdb(struct gk20a *g, struct mem_desc *inst_block, |
4129 | struct vm_gk20a *vm) | 4211 | struct vm_gk20a *vm) |
4130 | { | 4212 | { |