summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorYishai Hadas <yishaih@mellanox.com>2012-08-13 12:15:06 +0400
committerRoland Dreier <roland@purestorage.com>2012-08-16 08:05:20 +0400
commit89dd86db78e08b51bab29e168fd41b2fd943e6b6 (patch)
treee2c69177fd4478c398547e81d5da2b61a1cd2158 /drivers
parentdf7fba66471c6bbbaebb55e1bb3658eb7ce00a9b (diff)
downloadlinux-89dd86db78e08b51bab29e168fd41b2fd943e6b6.tar.xz
mlx4_core: Allow large mlx4_buddy bitmaps
mlx4_buddy_init uses kmalloc() to allocate bitmaps, which fails when the required size is beyond the max supported value (or when memory is too fragmented to handle a huge allocation). Extend this to use use vmalloc() if kmalloc() fails, and take that into account when freeing the bitmaps as well. This fixes a driver load failure when log num mtt is 26 or higher, and is a step in the direction of allowing to register huge amounts of memory on large memory systems. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mr.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c
index af55b7ce5341..d6a3a392a377 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -37,6 +37,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/vmalloc.h>
#include <linux/mlx4/cmd.h>
@@ -130,8 +131,11 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
for (i = 0; i <= buddy->max_order; ++i) {
s = BITS_TO_LONGS(1 << (buddy->max_order - i));
buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
- if (!buddy->bits[i])
- goto err_out_free;
+ if (!buddy->bits[i]) {
+ buddy->bits[i] = vmalloc(s * sizeof(long));
+ if (!buddy->bits[i])
+ goto err_out_free;
+ }
bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i));
}
@@ -142,7 +146,10 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
- kfree(buddy->bits[i]);
+ if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i]))
+ vfree(buddy->bits[i]);
+ else
+ kfree(buddy->bits[i]);
err_out:
kfree(buddy->bits);
@@ -156,7 +163,10 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
int i;
for (i = 0; i <= buddy->max_order; ++i)
- kfree(buddy->bits[i]);
+ if (is_vmalloc_addr(buddy->bits[i]))
+ vfree(buddy->bits[i]);
+ else
+ kfree(buddy->bits[i]);
kfree(buddy->bits);
kfree(buddy->num_free);