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>
This commit is contained in:
parent
df7fba6647
commit
89dd86db78
1 changed files with 14 additions and 4 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue