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 | |
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(size: 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 | |
40 | void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev) |
41 | { |
42 | kfree(objp: dev->priv.ft_pool); |
43 | } |
44 | |
45 | int |
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 |
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 | |