1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021 Mellanox Technologies. */
3 
4 #include "fs_ft_pool.h"
5 
6 /* Firmware currently has 4 pool of 4 sizes that it supports (FT_POOLS),
7  * and a virtual memory region of 16M (MLX5_FT_SIZE), this region is duplicated
8  * for each flow table pool. We can allocate up to 16M of each pool,
9  * and we keep track of how much we used via mlx5_ft_pool_get_avail_sz.
10  * Firmware doesn't report any of this for now.
11  * ESW_POOL is expected to be sorted from large to small and match firmware
12  * pools.
13  */
14 #define FT_SIZE (16 * 1024 * 1024)
15 static const unsigned int FT_POOLS[] = { 4 * 1024 * 1024,
16 					 1 * 1024 * 1024,
17 					 64 * 1024,
18 					 128,
19 					 1 /* size for termination tables */ };
20 struct mlx5_ft_pool {
21 	int ft_left[ARRAY_SIZE(FT_POOLS)];
22 };
23 
mlx5_ft_pool_init(struct mlx5_core_dev * dev)24 int mlx5_ft_pool_init(struct mlx5_core_dev *dev)
25 {
26 	struct mlx5_ft_pool *ft_pool;
27 	int i;
28 
29 	ft_pool = kzalloc(sizeof(*ft_pool), GFP_KERNEL);
30 	if (!ft_pool)
31 		return -ENOMEM;
32 
33 	for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--)
34 		ft_pool->ft_left[i] = FT_SIZE / FT_POOLS[i];
35 
36 	dev->priv.ft_pool = ft_pool;
37 	return 0;
38 }
39 
mlx5_ft_pool_destroy(struct mlx5_core_dev * dev)40 void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev)
41 {
42 	kfree(dev->priv.ft_pool);
43 }
44 
45 int
mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev * dev,enum fs_flow_table_type table_type,int desired_size)46 mlx5_ft_pool_get_avail_sz(struct mlx5_core_dev *dev, enum fs_flow_table_type table_type,
47 			  int desired_size)
48 {
49 	u32 max_ft_size = 1 << MLX5_CAP_FLOWTABLE_TYPE(dev, log_max_ft_size, table_type);
50 	int i, found_i = -1;
51 
52 	for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) {
53 		if (dev->priv.ft_pool->ft_left[i] && FT_POOLS[i] >= desired_size &&
54 		    FT_POOLS[i] <= max_ft_size) {
55 			found_i = i;
56 			if (desired_size != POOL_NEXT_SIZE)
57 				break;
58 		}
59 	}
60 
61 	if (found_i != -1) {
62 		--dev->priv.ft_pool->ft_left[found_i];
63 		return FT_POOLS[found_i];
64 	}
65 
66 	return 0;
67 }
68 
69 void
mlx5_ft_pool_put_sz(struct mlx5_core_dev * dev,int sz)70 mlx5_ft_pool_put_sz(struct mlx5_core_dev *dev, int sz)
71 {
72 	int i;
73 
74 	if (!sz)
75 		return;
76 
77 	for (i = ARRAY_SIZE(FT_POOLS) - 1; i >= 0; i--) {
78 		if (sz == FT_POOLS[i]) {
79 			++dev->priv.ft_pool->ft_left[i];
80 			return;
81 		}
82 	}
83 
84 	WARN_ONCE(1, "Couldn't find size %d in flow table size pool", sz);
85 }
86