Commit | Line | Data |
---|---|---|
4a98544d PB |
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(sizeof(*ft_pool), GFP_KERNEL); | |
b74fc1ca DC |
30 | if (!ft_pool) |
31 | return -ENOMEM; | |
4a98544d PB |
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(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 | } |