Commit 89dd86db authored by Yishai Hadas's avatar Yishai Hadas Committed by Roland Dreier

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: default avatarYishai Hadas <yishaih@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent df7fba66
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/mlx4/cmd.h> #include <linux/mlx4/cmd.h>
...@@ -130,8 +131,11 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) ...@@ -130,8 +131,11 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
for (i = 0; i <= buddy->max_order; ++i) { for (i = 0; i <= buddy->max_order; ++i) {
s = BITS_TO_LONGS(1 << (buddy->max_order - i)); s = BITS_TO_LONGS(1 << (buddy->max_order - i));
buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
if (!buddy->bits[i]) {
buddy->bits[i] = vmalloc(s * sizeof(long));
if (!buddy->bits[i]) if (!buddy->bits[i])
goto err_out_free; goto err_out_free;
}
bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i));
} }
...@@ -142,6 +146,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) ...@@ -142,6 +146,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
err_out_free: err_out_free:
for (i = 0; i <= buddy->max_order; ++i) for (i = 0; i <= buddy->max_order; ++i)
if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i]))
vfree(buddy->bits[i]);
else
kfree(buddy->bits[i]); kfree(buddy->bits[i]);
err_out: err_out:
...@@ -156,6 +163,9 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) ...@@ -156,6 +163,9 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
int i; int i;
for (i = 0; i <= buddy->max_order; ++i) for (i = 0; i <= buddy->max_order; ++i)
if (is_vmalloc_addr(buddy->bits[i]))
vfree(buddy->bits[i]);
else
kfree(buddy->bits[i]); kfree(buddy->bits[i]);
kfree(buddy->bits); kfree(buddy->bits);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment