]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
IB/ehca: Fall back to vmalloc() for big allocations
authorStefan Roscher <ossrosch@linux.vnet.ibm.com>
Wed, 13 May 2009 23:52:42 +0000 (16:52 -0700)
committerRoland Dreier <rolandd@cisco.com>
Wed, 13 May 2009 23:52:42 +0000 (16:52 -0700)
In case of large queue pairs there is the possibillity of allocation
failures due to memory fragmentation when using kmalloc().  To ensure
the memory is allocated even if kmalloc() can not find chunks which
are big enough, we fall back to allocating the memory with vmalloc().

Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/ehca/ipz_pt_fn.c

index a2605593ae797c1a87e8f1aea87ab2d8be248a50..1227c593627a62b5a1e27a237a63175c4038dfe0 100644 (file)
@@ -222,8 +222,11 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
        /* allocate queue page pointers */
        queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
        if (!queue->queue_pages) {
-               ehca_gen_err("Couldn't allocate queue page list");
-               return 0;
+               queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));
+               if (!queue->queue_pages) {
+                       ehca_gen_err("Couldn't allocate queue page list");
+                       return 0;
+               }
        }
        memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *));
 
@@ -240,7 +243,10 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
 ipz_queue_ctor_exit0:
        ehca_gen_err("Couldn't alloc pages queue=%p "
                 "nr_of_pages=%x",  queue, nr_of_pages);
-       kfree(queue->queue_pages);
+       if (is_vmalloc_addr(queue->queue_pages))
+               vfree(queue->queue_pages);
+       else
+               kfree(queue->queue_pages);
 
        return 0;
 }
@@ -262,7 +268,10 @@ int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue)
                        free_page((unsigned long)queue->queue_pages[i]);
        }
 
-       kfree(queue->queue_pages);
+       if (is_vmalloc_addr(queue->queue_pages))
+               vfree(queue->queue_pages);
+       else
+               kfree(queue->queue_pages);
 
        return 1;
 }