Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -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]) {
			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,6 +146,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)

err_out_free:
	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]);

err_out:
@@ -156,6 +163,9 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
	int 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);