diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-02-26 17:37:43 -0500 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-04-04 21:59:26 -0400 |
commit | 7290a6cbd5d03145d6f1ca4c3eacba40f6d4f93c (patch) | |
tree | de452c09f5eef76af273041dc64997fdc351dbd6 /drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |
parent | bb51cf9ec6482b50f3020179965ef82f58d91a0a (diff) |
gpu: nvgpu: Implement common allocator and mem_desc
Introduce mem_desc, which holds all information needed for a buffer.
Implement helper functions for allocation and freeing that use this
data type.
Change-Id: I82c88595d058d4fb8c5c5fbf19d13269e48e422f
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/712699
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index c3895a53..954249c6 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -268,7 +268,7 @@ static int gk20a_init_mm_reset_enable_hw(struct gk20a *g) | |||
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | static void gk20a_remove_vm(struct vm_gk20a *vm, struct inst_desc *inst_block) | 271 | static void gk20a_remove_vm(struct vm_gk20a *vm, struct mem_desc *inst_block) |
272 | { | 272 | { |
273 | struct gk20a *g = vm->mm->g; | 273 | struct gk20a *g = vm->mm->g; |
274 | 274 | ||
@@ -335,8 +335,8 @@ int gk20a_init_mm_setup_sw(struct gk20a *g) | |||
335 | int gk20a_init_mm_setup_hw(struct gk20a *g) | 335 | int gk20a_init_mm_setup_hw(struct gk20a *g) |
336 | { | 336 | { |
337 | struct mm_gk20a *mm = &g->mm; | 337 | struct mm_gk20a *mm = &g->mm; |
338 | struct inst_desc *inst_block = &mm->bar1.inst_block; | 338 | struct mem_desc *inst_block = &mm->bar1.inst_block; |
339 | phys_addr_t inst_pa = inst_block->cpu_pa; | 339 | phys_addr_t inst_pa = gk20a_mem_phys(inst_block); |
340 | int err; | 340 | int err; |
341 | 341 | ||
342 | gk20a_dbg_fn(""); | 342 | gk20a_dbg_fn(""); |
@@ -1516,54 +1516,95 @@ u64 gk20a_gmmu_map(struct vm_gk20a *vm, | |||
1516 | return vaddr; | 1516 | return vaddr; |
1517 | } | 1517 | } |
1518 | 1518 | ||
1519 | int gk20a_gmmu_alloc_map(struct vm_gk20a *vm, | 1519 | int gk20a_gmmu_alloc(struct gk20a *g, size_t size, struct mem_desc *mem) |
1520 | size_t size, struct mem_desc *mem) | 1520 | { |
1521 | return gk20a_gmmu_alloc_attr(g, 0, size, mem); | ||
1522 | } | ||
1523 | |||
1524 | int gk20a_gmmu_alloc_attr(struct gk20a *g, enum dma_attr attr, size_t size, struct mem_desc *mem) | ||
1521 | { | 1525 | { |
1522 | struct gk20a *g = vm->mm->g; | ||
1523 | struct device *d = dev_from_gk20a(g); | 1526 | struct device *d = dev_from_gk20a(g); |
1524 | int err; | 1527 | int err; |
1525 | struct sg_table *sgt; | 1528 | dma_addr_t iova; |
1529 | |||
1530 | gk20a_dbg_fn(""); | ||
1531 | |||
1532 | if (attr) { | ||
1533 | DEFINE_DMA_ATTRS(attrs); | ||
1534 | dma_set_attr(attr, &attrs); | ||
1535 | mem->cpu_va = | ||
1536 | dma_alloc_attrs(d, size, &iova, GFP_KERNEL, &attrs); | ||
1537 | } else { | ||
1538 | mem->cpu_va = dma_alloc_coherent(d, size, &iova, GFP_KERNEL); | ||
1539 | } | ||
1526 | 1540 | ||
1527 | mem->cpu_va = dma_alloc_coherent(d, size, &mem->iova, GFP_KERNEL); | ||
1528 | if (!mem->cpu_va) | 1541 | if (!mem->cpu_va) |
1529 | return -ENOMEM; | 1542 | return -ENOMEM; |
1530 | 1543 | ||
1531 | err = gk20a_get_sgtable(d, &sgt, mem->cpu_va, mem->iova, size); | 1544 | err = gk20a_get_sgtable(d, &mem->sgt, mem->cpu_va, iova, size); |
1532 | if (err) | 1545 | if (err) |
1533 | goto fail_free; | 1546 | goto fail_free; |
1534 | 1547 | ||
1535 | mem->gpu_va = gk20a_gmmu_map(vm, &sgt, size, 0, gk20a_mem_flag_none); | 1548 | mem->size = size; |
1536 | gk20a_free_sgtable(&sgt); | 1549 | memset(mem->cpu_va, 0, size); |
1550 | |||
1551 | gk20a_dbg_fn("done"); | ||
1552 | |||
1553 | return 0; | ||
1554 | |||
1555 | fail_free: | ||
1556 | dma_free_coherent(d, size, mem->cpu_va, iova); | ||
1557 | mem->cpu_va = NULL; | ||
1558 | mem->sgt = NULL; | ||
1559 | return err; | ||
1560 | } | ||
1561 | |||
1562 | void gk20a_gmmu_free(struct gk20a *g, struct mem_desc *mem) | ||
1563 | { | ||
1564 | struct device *d = dev_from_gk20a(g); | ||
1565 | |||
1566 | if (mem->cpu_va) | ||
1567 | dma_free_coherent(d, mem->size, mem->cpu_va, | ||
1568 | sg_dma_address(mem->sgt->sgl)); | ||
1569 | mem->cpu_va = NULL; | ||
1570 | |||
1571 | if (mem->sgt) | ||
1572 | gk20a_free_sgtable(&mem->sgt); | ||
1573 | } | ||
1574 | |||
1575 | int gk20a_gmmu_alloc_map(struct vm_gk20a *vm, size_t size, struct mem_desc *mem) | ||
1576 | { | ||
1577 | return gk20a_gmmu_alloc_map_attr(vm, 0, size, mem); | ||
1578 | } | ||
1579 | |||
1580 | int gk20a_gmmu_alloc_map_attr(struct vm_gk20a *vm, | ||
1581 | enum dma_attr attr, size_t size, struct mem_desc *mem) | ||
1582 | { | ||
1583 | int err = gk20a_gmmu_alloc_attr(vm->mm->g, attr, size, mem); | ||
1584 | |||
1585 | if (err) | ||
1586 | return err; | ||
1587 | |||
1588 | mem->gpu_va = gk20a_gmmu_map(vm, &mem->sgt, size, 0, gk20a_mem_flag_none); | ||
1537 | if (!mem->gpu_va) { | 1589 | if (!mem->gpu_va) { |
1538 | err = -ENOMEM; | 1590 | err = -ENOMEM; |
1539 | goto fail_free; | 1591 | goto fail_free; |
1540 | } | 1592 | } |
1541 | 1593 | ||
1542 | mem->size = size; | ||
1543 | |||
1544 | return 0; | 1594 | return 0; |
1545 | 1595 | ||
1546 | fail_free: | 1596 | fail_free: |
1547 | dma_free_coherent(d, size, mem->cpu_va, mem->iova); | 1597 | gk20a_gmmu_free(vm->mm->g, mem); |
1548 | mem->cpu_va = NULL; | ||
1549 | mem->iova = 0; | ||
1550 | |||
1551 | return err; | 1598 | return err; |
1552 | } | 1599 | } |
1553 | 1600 | ||
1554 | void gk20a_gmmu_unmap_free(struct vm_gk20a *vm, struct mem_desc *mem) | 1601 | void gk20a_gmmu_unmap_free(struct vm_gk20a *vm, struct mem_desc *mem) |
1555 | { | 1602 | { |
1556 | struct gk20a *g = vm->mm->g; | ||
1557 | struct device *d = dev_from_gk20a(g); | ||
1558 | |||
1559 | if (mem->gpu_va) | 1603 | if (mem->gpu_va) |
1560 | gk20a_gmmu_unmap(vm, mem->gpu_va, mem->size, gk20a_mem_flag_none); | 1604 | gk20a_gmmu_unmap(vm, mem->gpu_va, mem->size, gk20a_mem_flag_none); |
1561 | mem->gpu_va = 0; | 1605 | mem->gpu_va = 0; |
1562 | 1606 | ||
1563 | if (mem->cpu_va) | 1607 | gk20a_gmmu_free(vm->mm->g, mem); |
1564 | dma_free_coherent(d, mem->size, mem->cpu_va, mem->iova); | ||
1565 | mem->cpu_va = NULL; | ||
1566 | mem->iova = 0; | ||
1567 | } | 1608 | } |
1568 | 1609 | ||
1569 | dma_addr_t gk20a_mm_gpuva_to_iova_base(struct vm_gk20a *vm, u64 gpu_vaddr) | 1610 | dma_addr_t gk20a_mm_gpuva_to_iova_base(struct vm_gk20a *vm, u64 gpu_vaddr) |
@@ -2644,42 +2685,24 @@ void gk20a_deinit_vm(struct vm_gk20a *vm) | |||
2644 | kfree(vm->pdb.entries); | 2685 | kfree(vm->pdb.entries); |
2645 | } | 2686 | } |
2646 | 2687 | ||
2647 | int gk20a_alloc_inst_block(struct gk20a *g, struct inst_desc *inst_block) | 2688 | int gk20a_alloc_inst_block(struct gk20a *g, struct mem_desc *inst_block) |
2648 | { | 2689 | { |
2649 | struct device *dev = dev_from_gk20a(g); | 2690 | struct device *dev = dev_from_gk20a(g); |
2650 | dma_addr_t iova; | 2691 | int err; |
2651 | 2692 | ||
2652 | inst_block->size = ram_in_alloc_size_v(); | 2693 | err = gk20a_gmmu_alloc(g, ram_in_alloc_size_v(), inst_block); |
2653 | inst_block->cpuva = dma_alloc_coherent(dev, inst_block->size, | 2694 | if (err) { |
2654 | &iova, GFP_KERNEL); | ||
2655 | if (!inst_block->cpuva) { | ||
2656 | gk20a_err(dev, "%s: memory allocation failed\n", __func__); | 2695 | gk20a_err(dev, "%s: memory allocation failed\n", __func__); |
2657 | return -ENOMEM; | 2696 | return err; |
2658 | } | ||
2659 | |||
2660 | inst_block->iova = iova; | ||
2661 | inst_block->cpu_pa = gk20a_get_phys_from_iova(dev, inst_block->iova); | ||
2662 | if (!inst_block->cpu_pa) { | ||
2663 | gk20a_err(dev, "%s: failed to get phys address\n", __func__); | ||
2664 | gk20a_free_inst_block(g, inst_block); | ||
2665 | return -ENOMEM; | ||
2666 | } | 2697 | } |
2667 | 2698 | ||
2668 | memset(inst_block->cpuva, 0, inst_block->size); | ||
2669 | |||
2670 | return 0; | 2699 | return 0; |
2671 | } | 2700 | } |
2672 | 2701 | ||
2673 | void gk20a_free_inst_block(struct gk20a *g, struct inst_desc *inst_block) | 2702 | void gk20a_free_inst_block(struct gk20a *g, struct mem_desc *inst_block) |
2674 | { | 2703 | { |
2675 | struct device *dev = dev_from_gk20a(g); | 2704 | if (inst_block->cpu_va) |
2676 | 2705 | gk20a_gmmu_free(g, inst_block); | |
2677 | if (inst_block->cpuva) { | ||
2678 | dma_free_coherent(dev, inst_block->size, | ||
2679 | inst_block->cpuva, inst_block->iova); | ||
2680 | } | ||
2681 | |||
2682 | memset(inst_block, 0, sizeof(*inst_block)); | ||
2683 | } | 2706 | } |
2684 | 2707 | ||
2685 | static int gk20a_init_bar1_vm(struct mm_gk20a *mm) | 2708 | static int gk20a_init_bar1_vm(struct mm_gk20a *mm) |
@@ -2687,7 +2710,7 @@ static int gk20a_init_bar1_vm(struct mm_gk20a *mm) | |||
2687 | int err; | 2710 | int err; |
2688 | struct vm_gk20a *vm = &mm->bar1.vm; | 2711 | struct vm_gk20a *vm = &mm->bar1.vm; |
2689 | struct gk20a *g = gk20a_from_mm(mm); | 2712 | struct gk20a *g = gk20a_from_mm(mm); |
2690 | struct inst_desc *inst_block = &mm->bar1.inst_block; | 2713 | struct mem_desc *inst_block = &mm->bar1.inst_block; |
2691 | u32 big_page_size = gk20a_get_platform(g->dev)->default_big_page_size; | 2714 | u32 big_page_size = gk20a_get_platform(g->dev)->default_big_page_size; |
2692 | 2715 | ||
2693 | mm->bar1.aperture_size = bar1_aperture_size_mb_gk20a() << 20; | 2716 | mm->bar1.aperture_size = bar1_aperture_size_mb_gk20a() << 20; |
@@ -2713,7 +2736,7 @@ static int gk20a_init_system_vm(struct mm_gk20a *mm) | |||
2713 | int err; | 2736 | int err; |
2714 | struct vm_gk20a *vm = &mm->pmu.vm; | 2737 | struct vm_gk20a *vm = &mm->pmu.vm; |
2715 | struct gk20a *g = gk20a_from_mm(mm); | 2738 | struct gk20a *g = gk20a_from_mm(mm); |
2716 | struct inst_desc *inst_block = &mm->pmu.inst_block; | 2739 | struct mem_desc *inst_block = &mm->pmu.inst_block; |
2717 | u32 big_page_size = gk20a_get_platform(g->dev)->default_big_page_size; | 2740 | u32 big_page_size = gk20a_get_platform(g->dev)->default_big_page_size; |
2718 | 2741 | ||
2719 | mm->pmu.aperture_size = GK20A_PMU_VA_SIZE; | 2742 | mm->pmu.aperture_size = GK20A_PMU_VA_SIZE; |
@@ -2739,7 +2762,7 @@ static int gk20a_init_hwpm(struct mm_gk20a *mm) | |||
2739 | int err; | 2762 | int err; |
2740 | struct vm_gk20a *vm = &mm->pmu.vm; | 2763 | struct vm_gk20a *vm = &mm->pmu.vm; |
2741 | struct gk20a *g = gk20a_from_mm(mm); | 2764 | struct gk20a *g = gk20a_from_mm(mm); |
2742 | struct inst_desc *inst_block = &mm->hwpm.inst_block; | 2765 | struct mem_desc *inst_block = &mm->hwpm.inst_block; |
2743 | 2766 | ||
2744 | err = gk20a_alloc_inst_block(g, inst_block); | 2767 | err = gk20a_alloc_inst_block(g, inst_block); |
2745 | if (err) | 2768 | if (err) |
@@ -2763,13 +2786,13 @@ void gk20a_mm_init_pdb(struct gk20a *g, void *inst_ptr, u64 pdb_addr) | |||
2763 | ram_in_page_dir_base_hi_f(pdb_addr_hi)); | 2786 | ram_in_page_dir_base_hi_f(pdb_addr_hi)); |
2764 | } | 2787 | } |
2765 | 2788 | ||
2766 | void gk20a_init_inst_block(struct inst_desc *inst_block, struct vm_gk20a *vm, | 2789 | void gk20a_init_inst_block(struct mem_desc *inst_block, struct vm_gk20a *vm, |
2767 | u32 big_page_size) | 2790 | u32 big_page_size) |
2768 | { | 2791 | { |
2769 | struct gk20a *g = gk20a_from_vm(vm); | 2792 | struct gk20a *g = gk20a_from_vm(vm); |
2770 | u64 pde_addr = gk20a_mm_iova_addr(g, vm->pdb.sgt->sgl); | 2793 | u64 pde_addr = gk20a_mm_iova_addr(g, vm->pdb.sgt->sgl); |
2771 | phys_addr_t inst_pa = inst_block->cpu_pa; | 2794 | phys_addr_t inst_pa = gk20a_mem_phys(inst_block); |
2772 | void *inst_ptr = inst_block->cpuva; | 2795 | void *inst_ptr = inst_block->cpu_va; |
2773 | 2796 | ||
2774 | gk20a_dbg_info("inst block phys = 0x%llx, kv = 0x%p", | 2797 | gk20a_dbg_info("inst block phys = 0x%llx, kv = 0x%p", |
2775 | (u64)inst_pa, inst_ptr); | 2798 | (u64)inst_pa, inst_ptr); |