]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
gpu: nvgpu: Fix OOM case for buddy allocator
authorAlex Waterman <alexw@nvidia.com>
Wed, 20 May 2015 19:23:01 +0000 (12:23 -0700)
committerTerje Bergstrom <tbergstrom@nvidia.com>
Thu, 21 May 2015 22:36:59 +0000 (15:36 -0700)
The allocator could attempt to use a buddy list for an order larger than
the max order when all the valid buddy lists were empty. This patch
ensures that when looking for a particular order buddy that the passed
order is valid.

Also handle the prints in the no-mem case a litle differently. Only print
and update alloc info when there was a successful allocation.

Lastly print hex numbers for the allocator stats printing function.

Change-Id: If289f3e8925e236e3b7d84206a75bd45a14082a1
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: http://git-master/r/745071
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
drivers/gpu/nvgpu/gk20a/gk20a_allocator.c

index 56fb22df3126ea9e5cbe91ca2cf55c62a131154a..badfcd9f83611db608d04b78f1e6eb58620c164f 100644 (file)
@@ -573,7 +573,8 @@ static struct gk20a_buddy *__balloc_find_buddy(struct gk20a_allocator *a,
 {
        struct gk20a_buddy *bud;
 
-       if (list_empty(balloc_get_order_list(a, order)))
+       if (order > a->max_order ||
+           list_empty(balloc_get_order_list(a, order)))
                return NULL;
 
        if (a->flags & GPU_BALLOC_GVA_SPACE &&
@@ -609,6 +610,10 @@ static u64 __balloc_do_alloc(struct gk20a_allocator *a, u64 order, int pte_size)
        while (!(bud = __balloc_find_buddy(a, split_order, pte_size)))
                split_order++;
 
+       /* Out of memory! */
+       if (!bud)
+               return 0;
+
        while (bud->order != order) {
                if (balloc_split_buddy(a, bud, pte_size))
                        return 0; /* No mem... */
@@ -658,15 +663,19 @@ u64 gk20a_balloc(struct gk20a_allocator *a, u64 len)
 
        addr = __balloc_do_alloc(a, order, pte_size);
 
-       a->bytes_alloced += len;
-       a->bytes_alloced_real += balloc_order_to_len(a, order);
+       if (addr) {
+               a->bytes_alloced += len;
+               a->bytes_alloced_real += balloc_order_to_len(a, order);
+               balloc_dbg(a, "Alloc 0x%-10llx %3lld:0x%-10llx pte_size=%s\n",
+                          addr, order, len,
+                          pte_size == gmmu_page_size_big   ? "big" :
+                          pte_size == gmmu_page_size_small ? "small" :
+                          "NA/any");
+       } else {
+               balloc_dbg(a, "Alloc failed: no mem!\n");
+       }
 
        balloc_unlock(a);
-       balloc_dbg(a, "Alloc 0x%-10llx %3lld:0x%-10llx pte_size=%s\n",
-                  addr, order, len,
-                  pte_size == gmmu_page_size_big   ? "big" :
-                  pte_size == gmmu_page_size_small ? "small" :
-                  "NA/any");
 
        balloc_trace_func_done();
        return addr;
@@ -1071,11 +1080,11 @@ static void balloc_print_stats(struct gk20a_allocator *a, struct seq_file *s,
        __balloc_pstat(s, "base = %llu, limit = %llu, blk_size = %llu\n",
                   a->base, a->length, a->blk_size);
        __balloc_pstat(s, "Internal params:\n");
-       __balloc_pstat(s, "  start = %llu\n", a->start);
-       __balloc_pstat(s, "  end   = %llu\n", a->end);
-       __balloc_pstat(s, "  count = %llu\n", a->count);
-       __balloc_pstat(s, "  blks  = %llu\n", a->blks);
-       __balloc_pstat(s, "  max_order  = %llu\n", a->max_order);
+       __balloc_pstat(s, "  start = 0x%llx\n", a->start);
+       __balloc_pstat(s, "  end   = 0x%llx\n", a->end);
+       __balloc_pstat(s, "  count = 0x%llx\n", a->count);
+       __balloc_pstat(s, "  blks  = 0x%llx\n", a->blks);
+       __balloc_pstat(s, "  max_order = %llu\n", a->max_order);
 
        __balloc_pstat(s, "Buddy blocks:\n");
        __balloc_pstat(s, "  Order   Free    Alloced   Split\n");