linux/drivers/net/ethernet/mellanox/mlx5/core/fs_ft_pool.c
<<
>>
Prefs
   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)
  15static const unsigned int FT_POOLS[] = { 4 * 1024 * 1024,
  16                                         1 * 1024 * 1024,
  17                                         64 * 1024,
  18                                         128,
  19                                         1 /* size for termination tables */ };
  20struct mlx5_ft_pool {
  21        int ft_left[ARRAY_SIZE(FT_POOLS)];
  22};
  23
  24int 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
  40void mlx5_ft_pool_destroy(struct mlx5_core_dev *dev)
  41{
  42        kfree(dev->priv.ft_pool);
  43}
  44
  45int
  46mlx5_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
  69void
  70mlx5_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