diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-02-25 18:13:19 -0500 |
---|---|---|
committer | Alexander Van Brunt <avanbrunt@nvidia.com> | 2015-05-05 16:55:44 -0400 |
commit | d47b01d74f66ea1f1d68976dc4d602b4e299bd90 (patch) | |
tree | c0e2f9f5ae78cfc08741d85874f16386f5db1c32 /drivers/gpu/nvgpu | |
parent | 06be77da376f71ac9c73087ac02565cb6eec0eca (diff) |
gpu: nvgpu: Free all page table levels
Convert the loop to free page tables into a recursive loop that goes
through all levels.
Change-Id: I3ab8f021bd8263f2f6dad29b5fbd0e6212c55a86
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/711393
Reviewed-on: http://git-master/r/737528
Reviewed-by: Alexander Van Brunt <avanbrunt@nvidia.com>
Tested-by: Alexander Van Brunt <avanbrunt@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 43758712..45f6fd64 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -530,7 +530,9 @@ void free_gmmu_pages(struct vm_gk20a *vm, | |||
530 | DEFINE_DMA_ATTRS(attrs); | 530 | DEFINE_DMA_ATTRS(attrs); |
531 | 531 | ||
532 | gk20a_dbg_fn(""); | 532 | gk20a_dbg_fn(""); |
533 | BUG_ON(entry->sgt == NULL); | 533 | |
534 | if (!entry->sgt) | ||
535 | return; | ||
534 | 536 | ||
535 | if (tegra_platform_is_linsim()) { | 537 | if (tegra_platform_is_linsim()) { |
536 | free_gmmu_phys_pages(vm, entry); | 538 | free_gmmu_phys_pages(vm, entry); |
@@ -554,6 +556,7 @@ void free_gmmu_pages(struct vm_gk20a *vm, | |||
554 | entry->pages = NULL; | 556 | entry->pages = NULL; |
555 | } | 557 | } |
556 | entry->size = 0; | 558 | entry->size = 0; |
559 | entry->sgt = NULL; | ||
557 | } | 560 | } |
558 | 561 | ||
559 | int map_gmmu_pages(struct gk20a_mm_entry *entry) | 562 | int map_gmmu_pages(struct gk20a_mm_entry *entry) |
@@ -2140,13 +2143,28 @@ void gk20a_vm_unmap(struct vm_gk20a *vm, u64 offset) | |||
2140 | mutex_unlock(&vm->update_gmmu_lock); | 2143 | mutex_unlock(&vm->update_gmmu_lock); |
2141 | } | 2144 | } |
2142 | 2145 | ||
2146 | static void gk20a_vm_free_entries(struct vm_gk20a *vm, | ||
2147 | struct gk20a_mm_entry *parent, | ||
2148 | int level) | ||
2149 | { | ||
2150 | const struct gk20a_mmu_level *l = &vm->mmu_levels[level]; | ||
2151 | int num_entries = 1 << (l->hi_bit[parent->pgsz] - l->lo_bit[parent->pgsz]); | ||
2152 | int i; | ||
2153 | |||
2154 | if (parent->entries) | ||
2155 | for (i = 0; i < num_entries; i++) | ||
2156 | gk20a_vm_free_entries(vm, &parent->entries[i], level+1); | ||
2157 | |||
2158 | if (parent->size) | ||
2159 | free_gmmu_pages(vm, parent); | ||
2160 | kfree(parent->entries); | ||
2161 | } | ||
2162 | |||
2143 | static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm) | 2163 | static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm) |
2144 | { | 2164 | { |
2145 | struct mapped_buffer_node *mapped_buffer; | 2165 | struct mapped_buffer_node *mapped_buffer; |
2146 | struct vm_reserved_va_node *va_node, *va_node_tmp; | 2166 | struct vm_reserved_va_node *va_node, *va_node_tmp; |
2147 | struct rb_node *node; | 2167 | struct rb_node *node; |
2148 | int i; | ||
2149 | u32 pde_lo = 0, pde_hi = 0; | ||
2150 | 2168 | ||
2151 | gk20a_dbg_fn(""); | 2169 | gk20a_dbg_fn(""); |
2152 | mutex_lock(&vm->update_gmmu_lock); | 2170 | mutex_lock(&vm->update_gmmu_lock); |
@@ -2169,17 +2187,6 @@ static void gk20a_vm_remove_support_nofree(struct vm_gk20a *vm) | |||
2169 | kfree(va_node); | 2187 | kfree(va_node); |
2170 | } | 2188 | } |
2171 | 2189 | ||
2172 | /* unmapping all buffers above may not actually free | ||
2173 | * all vm ptes. jettison them here for certain... */ | ||
2174 | pde_range_from_vaddr_range(vm, | ||
2175 | 0, vm->va_limit-1, | ||
2176 | &pde_lo, &pde_hi); | ||
2177 | for (i = 0; i < pde_hi + 1; i++) { | ||
2178 | struct gk20a_mm_entry *entry = &vm->pdb.entries[i]; | ||
2179 | if (entry->size) | ||
2180 | free_gmmu_pages(vm, entry); | ||
2181 | } | ||
2182 | |||
2183 | gk20a_deinit_vm(vm); | 2190 | gk20a_deinit_vm(vm); |
2184 | 2191 | ||
2185 | mutex_unlock(&vm->update_gmmu_lock); | 2192 | mutex_unlock(&vm->update_gmmu_lock); |
@@ -2709,9 +2716,7 @@ void gk20a_deinit_vm(struct vm_gk20a *vm) | |||
2709 | gk20a_allocator_destroy(&vm->vma[gmmu_page_size_big]); | 2716 | gk20a_allocator_destroy(&vm->vma[gmmu_page_size_big]); |
2710 | gk20a_allocator_destroy(&vm->vma[gmmu_page_size_small]); | 2717 | gk20a_allocator_destroy(&vm->vma[gmmu_page_size_small]); |
2711 | 2718 | ||
2712 | unmap_gmmu_pages(&vm->pdb); | 2719 | gk20a_vm_free_entries(vm, &vm->pdb, 0); |
2713 | free_gmmu_pages(vm, &vm->pdb); | ||
2714 | kfree(vm->pdb.entries); | ||
2715 | } | 2720 | } |
2716 | 2721 | ||
2717 | int gk20a_alloc_inst_block(struct gk20a *g, struct mem_desc *inst_block) | 2722 | int gk20a_alloc_inst_block(struct gk20a *g, struct mem_desc *inst_block) |