Skip to content

Commit 1383cb8

Browse files
GoKu-Gear6davem330
authored andcommitted
mlx4_core: allocate ICM memory in page size chunks
When a system is under memory presure (high usage with fragments), the original 256KB ICM chunk allocations will likely trigger kernel memory management to enter slow path doing memory compact/migration ops in order to complete high order memory allocations. When that happens, user processes calling uverb APIs may get stuck for more than 120s easily even though there are a lot of free pages in smaller chunks available in the system. Syslog: ... Dec 10 09:04:51 slcc03db02 kernel: [397078.572732] INFO: task oracle_205573_e:205573 blocked for more than 120 seconds. ... With 4KB ICM chunk size on x86_64 arch, the above issue is fixed. However in order to support smaller ICM chunk size, we need to fix another issue in large size kcalloc allocations. E.g. Setting log_num_mtt=30 requires 1G mtt entries. With the 4KB ICM chunk size, each ICM chunk can only hold 512 mtt entries (8 bytes for each mtt entry). So we need a 16MB allocation for a table->icm pointer array to hold 2M pointers which can easily cause kcalloc to fail. The solution is to use kvzalloc to replace kcalloc which will fall back to vmalloc automatically if kmalloc fails. Signed-off-by: Qing Huang <qing.huang@oracle.com> Acked-by: Daniel Jurgens <danielj@mellanox.com> Reviewed-by: Zhu Yanjun <yanjun.zhu@oracle.com> Reviewed-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 322eaa0 commit 1383cb8

File tree

1 file changed

+9
-7
lines changed
  • drivers/net/ethernet/mellanox/mlx4

1 file changed

+9
-7
lines changed

drivers/net/ethernet/mellanox/mlx4/icm.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@
4343
#include "fw.h"
4444

4545
/*
46-
* We allocate in as big chunks as we can, up to a maximum of 256 KB
47-
* per chunk.
46+
* We allocate in page size (default 4KB on many archs) chunks to avoid high
47+
* order memory allocations in fragmented/high usage memory situation.
4848
*/
4949
enum {
50-
MLX4_ICM_ALLOC_SIZE = 1 << 18,
51-
MLX4_TABLE_CHUNK_SIZE = 1 << 18
50+
MLX4_ICM_ALLOC_SIZE = PAGE_SIZE,
51+
MLX4_TABLE_CHUNK_SIZE = PAGE_SIZE,
5252
};
5353

5454
static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
@@ -398,9 +398,11 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
398398
u64 size;
399399

400400
obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size;
401+
if (WARN_ON(!obj_per_chunk))
402+
return -EINVAL;
401403
num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk;
402404

403-
table->icm = kcalloc(num_icm, sizeof(*table->icm), GFP_KERNEL);
405+
table->icm = kvzalloc(num_icm * sizeof(*table->icm), GFP_KERNEL);
404406
if (!table->icm)
405407
return -ENOMEM;
406408
table->virt = virt;
@@ -446,7 +448,7 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
446448
mlx4_free_icm(dev, table->icm[i], use_coherent);
447449
}
448450

449-
kfree(table->icm);
451+
kvfree(table->icm);
450452

451453
return -ENOMEM;
452454
}
@@ -462,5 +464,5 @@ void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table)
462464
mlx4_free_icm(dev, table->icm[i], table->coherent);
463465
}
464466

465-
kfree(table->icm);
467+
kvfree(table->icm);
466468
}

0 commit comments

Comments
 (0)