gpu: nvgpu: fix pte memory leak
Kirill Artamonov [Fri, 16 May 2014 22:09:07 +0000 (01:09 +0300)]
Force cleanup of all GMMU PTEs when releasing vm.

bug 1514178

Signed-off-by: Kirill Artamonov <kartamonov@nvidia.com>
Change-Id: Ice1ff837ca4decbdec2d4a78ea5eb64bfeefc0db
Reviewed-on: http://git-master/r/411198
(cherry picked from commit e14ee5646554fd6cd812f4e7edf220c40116d722)
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/411895
Reviewed-by: Thomas Cherry <tcherry@nvidia.com>
Tested-by: Ishwarya Balaji Gururajan <igururajan@nvidia.com>

drivers/gpu/nvgpu/gk20a/mm_gk20a.c

index 1d6cdb5..9de589f 100644 (file)
@@ -2013,6 +2013,7 @@ static void gk20a_vm_remove_support(struct vm_gk20a *vm)
        struct mapped_buffer_node *mapped_buffer;
        struct vm_reserved_va_node *va_node, *va_node_tmp;
        struct rb_node *node;
+       int i;
 
        gk20a_dbg_fn("");
        mutex_lock(&vm->update_gmmu_lock);
@@ -2035,8 +2036,25 @@ static void gk20a_vm_remove_support(struct vm_gk20a *vm)
                kfree(va_node);
        }
 
-       /* TBD: unmapping all buffers above may not actually free
+       /* unmapping all buffers above may not actually free
         * all vm ptes.  jettison them here for certain... */
+       for (i = 0; i < vm->pdes.num_pdes; i++) {
+               struct page_table_gk20a *pte =
+                       &vm->pdes.ptes[gmmu_page_size_small][i];
+               if (pte->ref) {
+                       free_gmmu_pages(vm, pte->ref, pte->sgt,
+                               vm->mm->page_table_sizing[gmmu_page_size_small].order,
+                               pte->size);
+                       pte->ref = NULL;
+               }
+               pte = &vm->pdes.ptes[gmmu_page_size_big][i];
+               if (pte->ref) {
+                       free_gmmu_pages(vm, pte->ref, pte->sgt,
+                               vm->mm->page_table_sizing[gmmu_page_size_big].order,
+                               pte->size);
+                       pte->ref = NULL;
+               }
+       }
 
        unmap_gmmu_pages(vm->pdes.ref, vm->pdes.sgt, vm->pdes.kv);
        free_gmmu_pages(vm, vm->pdes.ref, vm->pdes.sgt, 0, vm->pdes.size);