diff options
author | Yishai Hadas <yishaih@mellanox.com> | 2012-08-13 04:15:06 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-08-16 00:05:20 -0400 |
commit | 89dd86db78e08b51bab29e168fd41b2fd943e6b6 (patch) | |
tree | e2c69177fd4478c398547e81d5da2b61a1cd2158 /drivers/net | |
parent | df7fba66471c6bbbaebb55e1bb3658eb7ce00a9b (diff) |
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/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mr.c | 18 |
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 @@ | |||
37 | #include <linux/export.h> | 37 | #include <linux/export.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
40 | #include <linux/vmalloc.h> | ||
40 | 41 | ||
41 | #include <linux/mlx4/cmd.h> | 42 | #include <linux/mlx4/cmd.h> |
42 | 43 | ||
@@ -130,8 +131,11 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) | |||
130 | for (i = 0; i <= buddy->max_order; ++i) { | 131 | for (i = 0; i <= buddy->max_order; ++i) { |
131 | s = BITS_TO_LONGS(1 << (buddy->max_order - i)); | 132 | s = BITS_TO_LONGS(1 << (buddy->max_order - i)); |
132 | buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); | 133 | buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); |
133 | if (!buddy->bits[i]) | 134 | if (!buddy->bits[i]) { |
134 | goto err_out_free; | 135 | buddy->bits[i] = vmalloc(s * sizeof(long)); |
136 | if (!buddy->bits[i]) | ||
137 | goto err_out_free; | ||
138 | } | ||
135 | bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); | 139 | bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); |
136 | } | 140 | } |
137 | 141 | ||
@@ -142,7 +146,10 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order) | |||
142 | 146 | ||
143 | err_out_free: | 147 | err_out_free: |
144 | for (i = 0; i <= buddy->max_order; ++i) | 148 | for (i = 0; i <= buddy->max_order; ++i) |
145 | kfree(buddy->bits[i]); | 149 | if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i])) |
150 | vfree(buddy->bits[i]); | ||
151 | else | ||
152 | kfree(buddy->bits[i]); | ||
146 | 153 | ||
147 | err_out: | 154 | err_out: |
148 | kfree(buddy->bits); | 155 | kfree(buddy->bits); |
@@ -156,7 +163,10 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) | |||
156 | int i; | 163 | int i; |
157 | 164 | ||
158 | for (i = 0; i <= buddy->max_order; ++i) | 165 | for (i = 0; i <= buddy->max_order; ++i) |
159 | kfree(buddy->bits[i]); | 166 | if (is_vmalloc_addr(buddy->bits[i])) |
167 | vfree(buddy->bits[i]); | ||
168 | else | ||
169 | kfree(buddy->bits[i]); | ||
160 | 170 | ||
161 | kfree(buddy->bits); | 171 | kfree(buddy->bits); |
162 | kfree(buddy->num_free); | 172 | kfree(buddy->num_free); |