diff options
author | Yishai Hadas <yishaih@mellanox.com> | 2012-08-29 11:14:35 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-09-13 20:52:02 -0400 |
commit | dd03e73481564fe57655d37154f84a0af00cb449 (patch) | |
tree | bfccd072c4492919bd29c4c2cbf85847a1c21a12 | |
parent | fea7a08acb13524b47711625eebea40a0ede69a0 (diff) |
mlx4_core: Fix integer overflows so 8TBs of memory registration works
This patch adds on the fixes done in commits 89dd86db78e0 ("mlx4_core:
Allow large mlx4_buddy bitmaps") and 3de819e6b642 ("mlx4_core: Fix
integer overflow issues around MTT table") so that memory registration
of up to 8TB (log_num_mtt=31) finally works.
It fixes integer overflows in a few mlx4_table_yyy routines in icm.c
by using a u64 intermediate variable, and int/uint issues that caused
table indexes to become nagive by setting some variables to be u32
instead of int. These problems cause crashes when a user attempted to
register > 512GB of RAM.
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/icm.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/icm.h | 10 |
2 files changed, 23 insertions, 17 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index daf417923661..31d02649be41 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c | |||
@@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) | |||
227 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); | 227 | MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); |
228 | } | 228 | } |
229 | 229 | ||
230 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | 230 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) |
231 | { | 231 | { |
232 | int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); | 232 | u32 i = (obj & (table->num_obj - 1)) / |
233 | (MLX4_TABLE_CHUNK_SIZE / table->obj_size); | ||
233 | int ret = 0; | 234 | int ret = 0; |
234 | 235 | ||
235 | mutex_lock(&table->mutex); | 236 | mutex_lock(&table->mutex); |
@@ -262,16 +263,18 @@ out: | |||
262 | return ret; | 263 | return ret; |
263 | } | 264 | } |
264 | 265 | ||
265 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | 266 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj) |
266 | { | 267 | { |
267 | int i; | 268 | u32 i; |
269 | u64 offset; | ||
268 | 270 | ||
269 | i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); | 271 | i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size); |
270 | 272 | ||
271 | mutex_lock(&table->mutex); | 273 | mutex_lock(&table->mutex); |
272 | 274 | ||
273 | if (--table->icm[i]->refcount == 0) { | 275 | if (--table->icm[i]->refcount == 0) { |
274 | mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE, | 276 | offset = (u64) i * MLX4_TABLE_CHUNK_SIZE; |
277 | mlx4_UNMAP_ICM(dev, table->virt + offset, | ||
275 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); | 278 | MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE); |
276 | mlx4_free_icm(dev, table->icm[i], table->coherent); | 279 | mlx4_free_icm(dev, table->icm[i], table->coherent); |
277 | table->icm[i] = NULL; | 280 | table->icm[i] = NULL; |
@@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) | |||
280 | mutex_unlock(&table->mutex); | 283 | mutex_unlock(&table->mutex); |
281 | } | 284 | } |
282 | 285 | ||
283 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle) | 286 | void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, |
287 | dma_addr_t *dma_handle) | ||
284 | { | 288 | { |
285 | int idx, offset, dma_offset, i; | 289 | int offset, dma_offset, i; |
290 | u64 idx; | ||
286 | struct mlx4_icm_chunk *chunk; | 291 | struct mlx4_icm_chunk *chunk; |
287 | struct mlx4_icm *icm; | 292 | struct mlx4_icm *icm; |
288 | struct page *page = NULL; | 293 | struct page *page = NULL; |
@@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han | |||
292 | 297 | ||
293 | mutex_lock(&table->mutex); | 298 | mutex_lock(&table->mutex); |
294 | 299 | ||
295 | idx = (obj & (table->num_obj - 1)) * table->obj_size; | 300 | idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size; |
296 | icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE]; | 301 | icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE]; |
297 | dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; | 302 | dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE; |
298 | 303 | ||
@@ -326,10 +331,11 @@ out: | |||
326 | } | 331 | } |
327 | 332 | ||
328 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 333 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
329 | int start, int end) | 334 | u32 start, u32 end) |
330 | { | 335 | { |
331 | int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; | 336 | int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size; |
332 | int i, err; | 337 | int err; |
338 | u32 i; | ||
333 | 339 | ||
334 | for (i = start; i <= end; i += inc) { | 340 | for (i = start; i <= end; i += inc) { |
335 | err = mlx4_table_get(dev, table, i); | 341 | err = mlx4_table_get(dev, table, i); |
@@ -349,9 +355,9 @@ fail: | |||
349 | } | 355 | } |
350 | 356 | ||
351 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 357 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
352 | int start, int end) | 358 | u32 start, u32 end) |
353 | { | 359 | { |
354 | int i; | 360 | u32 i; |
355 | 361 | ||
356 | for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) | 362 | for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size) |
357 | mlx4_table_put(dev, table, i); | 363 | mlx4_table_put(dev, table, i); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index a67744f53506..dee67fa39107 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h | |||
@@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, | |||
71 | gfp_t gfp_mask, int coherent); | 71 | gfp_t gfp_mask, int coherent); |
72 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); | 72 | void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent); |
73 | 73 | ||
74 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 74 | int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); |
75 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj); | 75 | void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj); |
76 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 76 | int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
77 | int start, int end); | 77 | u32 start, u32 end); |
78 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 78 | void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
79 | int start, int end); | 79 | u32 start, u32 end); |
80 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, | 80 | int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, |
81 | u64 virt, int obj_size, u32 nobj, int reserved, | 81 | u64 virt, int obj_size, u32 nobj, int reserved, |
82 | int use_lowmem, int use_coherent); | 82 | int use_lowmem, int use_coherent); |
83 | void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); | 83 | void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table); |
84 | void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); | 84 | void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle); |
85 | 85 | ||
86 | static inline void mlx4_icm_first(struct mlx4_icm *icm, | 86 | static inline void mlx4_icm_first(struct mlx4_icm *icm, |
87 | struct mlx4_icm_iter *iter) | 87 | struct mlx4_icm_iter *iter) |