// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB /* Copyright (c) 2021 Mellanox Technologies. */ #include "fs_ft_pool.h" /* Firmware currently has 4 pool of 4 sizes that it supports (FT_POOLS), * and a virtual memory region of 16M (MLX5_FT_SIZE), this region is duplicated * for each flow table pool. We can allocate up to 16M of each pool, * and we keep track of how much we used via mlx5_ft_pool_get_avail_sz. * Firmware doesn't report any of this for now. * ESW_POOL is expected to be sorted from large to small and match firmware * pools. */ #define FT_SIZE (16 * 1024 * 1024) static const unsigned int FT_POOLS[] = { 4 * 1024 * 1024, 1 * 1024 * 1024, 64 * 1024, 128, 1 /* size for termination tables */ }; struct mlx5_ft_pool { int ft_left[ARRAY_SIZE(FT_POOLS)]; }; int mlx5_ft_pool_init(struct mlx5_core_dev *dev) { struct mlx5_ft_pool *ft_pool; int i; ft_pool = kzalloc(sizeof(*ft_pool), GFP_KERNEL); if (!ft_pool) return -ENOMEM; for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) ft_pool->ft_left[i] = FT_SIZE / FT_POOLS[i]; dev->priv.ft_pool = ft_pool; return 0; } void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev) { kfree(dev->priv.ft_pool); } int mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type table_type, int desired_size) { u32 max_ft_size = 1 << MLX5_CAP_FLOWTABLE_TYPE(dev, log_max_ft_size, table_type); int i, found_i = -1; for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) { if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size && FT_POOLS[i] <= max_ft_size) { found_i = i; if (desired_size != POOL_NEXT_SIZE) break; } } if (found_i != -1) { --dev->priv.ft_pool->ft_left[found_i]; return FT_POOLS[found_i]; } return 0; } void mlx5_ft_pool_put_sz(struct mlx5_core_dev *dev, int sz) { int i; if (!sz) return; for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) { if (sz == FT_POOLS[i]) { ++dev->priv.ft_pool->ft_left[i]; return; } } WARN_ONCE(1, "Couldn't find size %d in flow table size pool", sz); }