mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
net/mlx5: fs, add mlx5_fs_pool API
Refactor fc_pool API to create generic fs_pool API, as HW steering has more flow steering elements which can take advantage of the same pool of bulks API. Change fs_counters code to use the fs_pool API. Note, removed __counted_by from struct mlx5_fc_bulk as bulk_len is now inner struct member. It will be added back once __counted_by can support inner struct members. Signed-off-by: Moshe Shemesh <moshe@nvidia.com> Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com> Reviewed-by: Mark Bloch <mbloch@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Link: https://patch.msgid.link/20241219175841.1094544-5-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
95f68e06b4
commit
31d1356b8f
|
|
@ -17,7 +17,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
|
|||
fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \
|
||||
lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \
|
||||
diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o diag/reporter_vnic.o \
|
||||
fw_reset.o qos.o lib/tout.o lib/aso.o wc.o
|
||||
fw_reset.o qos.o lib/tout.o lib/aso.o wc.o fs_pool.o
|
||||
|
||||
#
|
||||
# Netdev basic
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/mlx5/fs.h>
|
||||
#include "mlx5_core.h"
|
||||
#include "fs_core.h"
|
||||
#include "fs_pool.h"
|
||||
#include "fs_cmd.h"
|
||||
|
||||
#define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000)
|
||||
|
|
@ -65,17 +66,6 @@ struct mlx5_fc {
|
|||
u64 lastbytes;
|
||||
};
|
||||
|
||||
struct mlx5_fc_pool {
|
||||
struct mlx5_core_dev *dev;
|
||||
struct mutex pool_lock; /* protects pool lists */
|
||||
struct list_head fully_used;
|
||||
struct list_head partially_used;
|
||||
struct list_head unused;
|
||||
int available_fcs;
|
||||
int used_fcs;
|
||||
int threshold;
|
||||
};
|
||||
|
||||
struct mlx5_fc_stats {
|
||||
struct xarray counters;
|
||||
|
||||
|
|
@ -86,13 +76,13 @@ struct mlx5_fc_stats {
|
|||
int bulk_query_len;
|
||||
bool bulk_query_alloc_failed;
|
||||
unsigned long next_bulk_query_alloc;
|
||||
struct mlx5_fc_pool fc_pool;
|
||||
struct mlx5_fs_pool fc_pool;
|
||||
};
|
||||
|
||||
static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev);
|
||||
static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool);
|
||||
static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool);
|
||||
static void mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc);
|
||||
static void mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev);
|
||||
static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool);
|
||||
static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fs_pool *fc_pool);
|
||||
static void mlx5_fc_pool_release_counter(struct mlx5_fs_pool *fc_pool, struct mlx5_fc *fc);
|
||||
|
||||
static int get_init_bulk_query_len(struct mlx5_core_dev *dev)
|
||||
{
|
||||
|
|
@ -447,11 +437,9 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
|
|||
/* Flow counter bluks */
|
||||
|
||||
struct mlx5_fc_bulk {
|
||||
struct list_head pool_list;
|
||||
struct mlx5_fs_bulk fs_bulk;
|
||||
u32 base_id;
|
||||
int bulk_len;
|
||||
unsigned long *bitmask;
|
||||
struct mlx5_fc fcs[] __counted_by(bulk_len);
|
||||
struct mlx5_fc fcs[];
|
||||
};
|
||||
|
||||
static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
|
||||
|
|
@ -461,16 +449,10 @@ static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
|
|||
counter->id = id;
|
||||
}
|
||||
|
||||
static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk)
|
||||
{
|
||||
return bitmap_weight(bulk->bitmask, bulk->bulk_len);
|
||||
}
|
||||
|
||||
static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
|
||||
static struct mlx5_fs_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
|
||||
{
|
||||
enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask;
|
||||
struct mlx5_fc_bulk *bulk;
|
||||
int err = -ENOMEM;
|
||||
struct mlx5_fc_bulk *fc_bulk;
|
||||
int bulk_len;
|
||||
u32 base_id;
|
||||
int i;
|
||||
|
|
@ -478,71 +460,97 @@ static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
|
|||
alloc_bitmask = MLX5_CAP_GEN(dev, flow_counter_bulk_alloc);
|
||||
bulk_len = alloc_bitmask > 0 ? MLX5_FC_BULK_NUM_FCS(alloc_bitmask) : 1;
|
||||
|
||||
bulk = kvzalloc(struct_size(bulk, fcs, bulk_len), GFP_KERNEL);
|
||||
if (!bulk)
|
||||
goto err_alloc_bulk;
|
||||
fc_bulk = kvzalloc(struct_size(fc_bulk, fcs, bulk_len), GFP_KERNEL);
|
||||
if (!fc_bulk)
|
||||
return NULL;
|
||||
|
||||
bulk->bitmask = kvcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
if (!bulk->bitmask)
|
||||
goto err_alloc_bitmask;
|
||||
if (mlx5_fs_bulk_init(dev, &fc_bulk->fs_bulk, bulk_len))
|
||||
goto fc_bulk_free;
|
||||
|
||||
err = mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id);
|
||||
if (err)
|
||||
goto err_mlx5_cmd_bulk_alloc;
|
||||
if (mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id))
|
||||
goto fs_bulk_cleanup;
|
||||
fc_bulk->base_id = base_id;
|
||||
for (i = 0; i < bulk_len; i++)
|
||||
mlx5_fc_init(&fc_bulk->fcs[i], fc_bulk, base_id + i);
|
||||
|
||||
bulk->base_id = base_id;
|
||||
bulk->bulk_len = bulk_len;
|
||||
for (i = 0; i < bulk_len; i++) {
|
||||
mlx5_fc_init(&bulk->fcs[i], bulk, base_id + i);
|
||||
set_bit(i, bulk->bitmask);
|
||||
}
|
||||
return &fc_bulk->fs_bulk;
|
||||
|
||||
return bulk;
|
||||
|
||||
err_mlx5_cmd_bulk_alloc:
|
||||
kvfree(bulk->bitmask);
|
||||
err_alloc_bitmask:
|
||||
kvfree(bulk);
|
||||
err_alloc_bulk:
|
||||
return ERR_PTR(err);
|
||||
fs_bulk_cleanup:
|
||||
mlx5_fs_bulk_cleanup(&fc_bulk->fs_bulk);
|
||||
fc_bulk_free:
|
||||
kvfree(fc_bulk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk)
|
||||
mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk)
|
||||
{
|
||||
if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) {
|
||||
struct mlx5_fc_bulk *fc_bulk = container_of(fs_bulk,
|
||||
struct mlx5_fc_bulk,
|
||||
fs_bulk);
|
||||
|
||||
if (mlx5_fs_bulk_get_free_amount(fs_bulk) < fs_bulk->bulk_len) {
|
||||
mlx5_core_err(dev, "Freeing bulk before all counters were released\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mlx5_cmd_fc_free(dev, bulk->base_id);
|
||||
kvfree(bulk->bitmask);
|
||||
kvfree(bulk);
|
||||
mlx5_cmd_fc_free(dev, fc_bulk->base_id);
|
||||
mlx5_fs_bulk_cleanup(fs_bulk);
|
||||
kvfree(fc_bulk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mlx5_fc *mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk)
|
||||
static void mlx5_fc_pool_update_threshold(struct mlx5_fs_pool *fc_pool)
|
||||
{
|
||||
int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len);
|
||||
|
||||
if (free_fc_index >= bulk->bulk_len)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
clear_bit(free_fc_index, bulk->bitmask);
|
||||
return &bulk->fcs[free_fc_index];
|
||||
fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD,
|
||||
fc_pool->used_units / MLX5_FC_POOL_USED_BUFF_RATIO);
|
||||
}
|
||||
|
||||
static int mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
|
||||
/* Flow counters pool API */
|
||||
|
||||
static const struct mlx5_fs_pool_ops mlx5_fc_pool_ops = {
|
||||
.bulk_destroy = mlx5_fc_bulk_destroy,
|
||||
.bulk_create = mlx5_fc_bulk_create,
|
||||
.update_threshold = mlx5_fc_pool_update_threshold,
|
||||
};
|
||||
|
||||
static void
|
||||
mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev)
|
||||
{
|
||||
int fc_index = fc->id - bulk->base_id;
|
||||
mlx5_fs_pool_init(fc_pool, dev, &mlx5_fc_pool_ops);
|
||||
}
|
||||
|
||||
if (test_bit(fc_index, bulk->bitmask))
|
||||
return -EINVAL;
|
||||
static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool)
|
||||
{
|
||||
mlx5_fs_pool_cleanup(fc_pool);
|
||||
}
|
||||
|
||||
set_bit(fc_index, bulk->bitmask);
|
||||
return 0;
|
||||
static struct mlx5_fc *
|
||||
mlx5_fc_pool_acquire_counter(struct mlx5_fs_pool *fc_pool)
|
||||
{
|
||||
struct mlx5_fs_pool_index pool_index = {};
|
||||
struct mlx5_fc_bulk *fc_bulk;
|
||||
int err;
|
||||
|
||||
err = mlx5_fs_pool_acquire_index(fc_pool, &pool_index);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
fc_bulk = container_of(pool_index.fs_bulk, struct mlx5_fc_bulk, fs_bulk);
|
||||
return &fc_bulk->fcs[pool_index.index];
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_fc_pool_release_counter(struct mlx5_fs_pool *fc_pool, struct mlx5_fc *fc)
|
||||
{
|
||||
struct mlx5_fs_bulk *fs_bulk = &fc->bulk->fs_bulk;
|
||||
struct mlx5_fs_pool_index pool_index = {};
|
||||
struct mlx5_core_dev *dev = fc_pool->dev;
|
||||
|
||||
pool_index.fs_bulk = fs_bulk;
|
||||
pool_index.index = fc->id - fc->bulk->base_id;
|
||||
if (mlx5_fs_pool_release_index(fc_pool, &pool_index))
|
||||
mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -573,7 +581,7 @@ mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size)
|
|||
counter->type = MLX5_FC_TYPE_LOCAL;
|
||||
counter->id = counter_id;
|
||||
fc_bulk->base_id = counter_id - offset;
|
||||
fc_bulk->bulk_len = bulk_size;
|
||||
fc_bulk->fs_bulk.bulk_len = bulk_size;
|
||||
counter->bulk = fc_bulk;
|
||||
return counter;
|
||||
}
|
||||
|
|
@ -588,141 +596,3 @@ void mlx5_fc_local_destroy(struct mlx5_fc *counter)
|
|||
kfree(counter);
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_fc_local_destroy);
|
||||
|
||||
/* Flow counters pool API */
|
||||
|
||||
static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev)
|
||||
{
|
||||
fc_pool->dev = dev;
|
||||
mutex_init(&fc_pool->pool_lock);
|
||||
INIT_LIST_HEAD(&fc_pool->fully_used);
|
||||
INIT_LIST_HEAD(&fc_pool->partially_used);
|
||||
INIT_LIST_HEAD(&fc_pool->unused);
|
||||
fc_pool->available_fcs = 0;
|
||||
fc_pool->used_fcs = 0;
|
||||
fc_pool->threshold = 0;
|
||||
}
|
||||
|
||||
static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fc_pool->dev;
|
||||
struct mlx5_fc_bulk *bulk;
|
||||
struct mlx5_fc_bulk *tmp;
|
||||
|
||||
list_for_each_entry_safe(bulk, tmp, &fc_pool->fully_used, pool_list)
|
||||
mlx5_fc_bulk_destroy(dev, bulk);
|
||||
list_for_each_entry_safe(bulk, tmp, &fc_pool->partially_used, pool_list)
|
||||
mlx5_fc_bulk_destroy(dev, bulk);
|
||||
list_for_each_entry_safe(bulk, tmp, &fc_pool->unused, pool_list)
|
||||
mlx5_fc_bulk_destroy(dev, bulk);
|
||||
}
|
||||
|
||||
static void mlx5_fc_pool_update_threshold(struct mlx5_fc_pool *fc_pool)
|
||||
{
|
||||
fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD,
|
||||
fc_pool->used_fcs / MLX5_FC_POOL_USED_BUFF_RATIO);
|
||||
}
|
||||
|
||||
static struct mlx5_fc_bulk *
|
||||
mlx5_fc_pool_alloc_new_bulk(struct mlx5_fc_pool *fc_pool)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fc_pool->dev;
|
||||
struct mlx5_fc_bulk *new_bulk;
|
||||
|
||||
new_bulk = mlx5_fc_bulk_create(dev);
|
||||
if (!IS_ERR(new_bulk))
|
||||
fc_pool->available_fcs += new_bulk->bulk_len;
|
||||
mlx5_fc_pool_update_threshold(fc_pool);
|
||||
return new_bulk;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_fc_pool_free_bulk(struct mlx5_fc_pool *fc_pool, struct mlx5_fc_bulk *bulk)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fc_pool->dev;
|
||||
|
||||
fc_pool->available_fcs -= bulk->bulk_len;
|
||||
mlx5_fc_bulk_destroy(dev, bulk);
|
||||
mlx5_fc_pool_update_threshold(fc_pool);
|
||||
}
|
||||
|
||||
static struct mlx5_fc *
|
||||
mlx5_fc_pool_acquire_from_list(struct list_head *src_list,
|
||||
struct list_head *next_list,
|
||||
bool move_non_full_bulk)
|
||||
{
|
||||
struct mlx5_fc_bulk *bulk;
|
||||
struct mlx5_fc *fc;
|
||||
|
||||
if (list_empty(src_list))
|
||||
return ERR_PTR(-ENODATA);
|
||||
|
||||
bulk = list_first_entry(src_list, struct mlx5_fc_bulk, pool_list);
|
||||
fc = mlx5_fc_bulk_acquire_fc(bulk);
|
||||
if (move_non_full_bulk || mlx5_fc_bulk_get_free_fcs_amount(bulk) == 0)
|
||||
list_move(&bulk->pool_list, next_list);
|
||||
return fc;
|
||||
}
|
||||
|
||||
static struct mlx5_fc *
|
||||
mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool)
|
||||
{
|
||||
struct mlx5_fc_bulk *new_bulk;
|
||||
struct mlx5_fc *fc;
|
||||
|
||||
mutex_lock(&fc_pool->pool_lock);
|
||||
|
||||
fc = mlx5_fc_pool_acquire_from_list(&fc_pool->partially_used,
|
||||
&fc_pool->fully_used, false);
|
||||
if (IS_ERR(fc))
|
||||
fc = mlx5_fc_pool_acquire_from_list(&fc_pool->unused,
|
||||
&fc_pool->partially_used,
|
||||
true);
|
||||
if (IS_ERR(fc)) {
|
||||
new_bulk = mlx5_fc_pool_alloc_new_bulk(fc_pool);
|
||||
if (IS_ERR(new_bulk)) {
|
||||
fc = ERR_CAST(new_bulk);
|
||||
goto out;
|
||||
}
|
||||
fc = mlx5_fc_bulk_acquire_fc(new_bulk);
|
||||
list_add(&new_bulk->pool_list, &fc_pool->partially_used);
|
||||
}
|
||||
fc_pool->available_fcs--;
|
||||
fc_pool->used_fcs++;
|
||||
|
||||
out:
|
||||
mutex_unlock(&fc_pool->pool_lock);
|
||||
return fc;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fc_pool->dev;
|
||||
struct mlx5_fc_bulk *bulk = fc->bulk;
|
||||
int bulk_free_fcs_amount;
|
||||
|
||||
mutex_lock(&fc_pool->pool_lock);
|
||||
|
||||
if (mlx5_fc_bulk_release_fc(bulk, fc)) {
|
||||
mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
fc_pool->available_fcs++;
|
||||
fc_pool->used_fcs--;
|
||||
|
||||
bulk_free_fcs_amount = mlx5_fc_bulk_get_free_fcs_amount(bulk);
|
||||
if (bulk_free_fcs_amount == 1)
|
||||
list_move_tail(&bulk->pool_list, &fc_pool->partially_used);
|
||||
if (bulk_free_fcs_amount == bulk->bulk_len) {
|
||||
list_del(&bulk->pool_list);
|
||||
if (fc_pool->available_fcs > fc_pool->threshold)
|
||||
mlx5_fc_pool_free_bulk(fc_pool, bulk);
|
||||
else
|
||||
list_add(&bulk->pool_list, &fc_pool->unused);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&fc_pool->pool_lock);
|
||||
}
|
||||
|
|
|
|||
194
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c
Normal file
194
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
|
||||
|
||||
#include <mlx5_core.h>
|
||||
#include "fs_pool.h"
|
||||
|
||||
int mlx5_fs_bulk_init(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk,
|
||||
int bulk_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
fs_bulk->bitmask = kvcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
if (!fs_bulk->bitmask)
|
||||
return -ENOMEM;
|
||||
|
||||
fs_bulk->bulk_len = bulk_len;
|
||||
for (i = 0; i < bulk_len; i++)
|
||||
set_bit(i, fs_bulk->bitmask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_fs_bulk_cleanup(struct mlx5_fs_bulk *fs_bulk)
|
||||
{
|
||||
kvfree(fs_bulk->bitmask);
|
||||
}
|
||||
|
||||
int mlx5_fs_bulk_get_free_amount(struct mlx5_fs_bulk *bulk)
|
||||
{
|
||||
return bitmap_weight(bulk->bitmask, bulk->bulk_len);
|
||||
}
|
||||
|
||||
static int mlx5_fs_bulk_acquire_index(struct mlx5_fs_bulk *fs_bulk,
|
||||
struct mlx5_fs_pool_index *pool_index)
|
||||
{
|
||||
int free_index = find_first_bit(fs_bulk->bitmask, fs_bulk->bulk_len);
|
||||
|
||||
WARN_ON_ONCE(!pool_index || !fs_bulk);
|
||||
if (free_index >= fs_bulk->bulk_len)
|
||||
return -ENOSPC;
|
||||
|
||||
clear_bit(free_index, fs_bulk->bitmask);
|
||||
pool_index->fs_bulk = fs_bulk;
|
||||
pool_index->index = free_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_fs_bulk_release_index(struct mlx5_fs_bulk *fs_bulk, int index)
|
||||
{
|
||||
if (test_bit(index, fs_bulk->bitmask))
|
||||
return -EINVAL;
|
||||
|
||||
set_bit(index, fs_bulk->bitmask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx5_fs_pool_init(struct mlx5_fs_pool *pool, struct mlx5_core_dev *dev,
|
||||
const struct mlx5_fs_pool_ops *ops)
|
||||
{
|
||||
WARN_ON_ONCE(!ops || !ops->bulk_destroy || !ops->bulk_create ||
|
||||
!ops->update_threshold);
|
||||
pool->dev = dev;
|
||||
mutex_init(&pool->pool_lock);
|
||||
INIT_LIST_HEAD(&pool->fully_used);
|
||||
INIT_LIST_HEAD(&pool->partially_used);
|
||||
INIT_LIST_HEAD(&pool->unused);
|
||||
pool->available_units = 0;
|
||||
pool->used_units = 0;
|
||||
pool->threshold = 0;
|
||||
pool->ops = ops;
|
||||
}
|
||||
|
||||
void mlx5_fs_pool_cleanup(struct mlx5_fs_pool *pool)
|
||||
{
|
||||
struct mlx5_core_dev *dev = pool->dev;
|
||||
struct mlx5_fs_bulk *bulk;
|
||||
struct mlx5_fs_bulk *tmp;
|
||||
|
||||
list_for_each_entry_safe(bulk, tmp, &pool->fully_used, pool_list)
|
||||
pool->ops->bulk_destroy(dev, bulk);
|
||||
list_for_each_entry_safe(bulk, tmp, &pool->partially_used, pool_list)
|
||||
pool->ops->bulk_destroy(dev, bulk);
|
||||
list_for_each_entry_safe(bulk, tmp, &pool->unused, pool_list)
|
||||
pool->ops->bulk_destroy(dev, bulk);
|
||||
}
|
||||
|
||||
static struct mlx5_fs_bulk *
|
||||
mlx5_fs_pool_alloc_new_bulk(struct mlx5_fs_pool *fs_pool)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fs_pool->dev;
|
||||
struct mlx5_fs_bulk *new_bulk;
|
||||
|
||||
new_bulk = fs_pool->ops->bulk_create(dev);
|
||||
if (new_bulk)
|
||||
fs_pool->available_units += new_bulk->bulk_len;
|
||||
fs_pool->ops->update_threshold(fs_pool);
|
||||
return new_bulk;
|
||||
}
|
||||
|
||||
static void
|
||||
mlx5_fs_pool_free_bulk(struct mlx5_fs_pool *fs_pool, struct mlx5_fs_bulk *bulk)
|
||||
{
|
||||
struct mlx5_core_dev *dev = fs_pool->dev;
|
||||
|
||||
fs_pool->available_units -= bulk->bulk_len;
|
||||
fs_pool->ops->bulk_destroy(dev, bulk);
|
||||
fs_pool->ops->update_threshold(fs_pool);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5_fs_pool_acquire_from_list(struct list_head *src_list,
|
||||
struct list_head *next_list,
|
||||
bool move_non_full_bulk,
|
||||
struct mlx5_fs_pool_index *pool_index)
|
||||
{
|
||||
struct mlx5_fs_bulk *fs_bulk;
|
||||
int err;
|
||||
|
||||
if (list_empty(src_list))
|
||||
return -ENODATA;
|
||||
|
||||
fs_bulk = list_first_entry(src_list, struct mlx5_fs_bulk, pool_list);
|
||||
err = mlx5_fs_bulk_acquire_index(fs_bulk, pool_index);
|
||||
if (move_non_full_bulk || mlx5_fs_bulk_get_free_amount(fs_bulk) == 0)
|
||||
list_move(&fs_bulk->pool_list, next_list);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_fs_pool_acquire_index(struct mlx5_fs_pool *fs_pool,
|
||||
struct mlx5_fs_pool_index *pool_index)
|
||||
{
|
||||
struct mlx5_fs_bulk *new_bulk;
|
||||
int err;
|
||||
|
||||
mutex_lock(&fs_pool->pool_lock);
|
||||
|
||||
err = mlx5_fs_pool_acquire_from_list(&fs_pool->partially_used,
|
||||
&fs_pool->fully_used, false,
|
||||
pool_index);
|
||||
if (err)
|
||||
err = mlx5_fs_pool_acquire_from_list(&fs_pool->unused,
|
||||
&fs_pool->partially_used,
|
||||
true, pool_index);
|
||||
if (err) {
|
||||
new_bulk = mlx5_fs_pool_alloc_new_bulk(fs_pool);
|
||||
if (!new_bulk) {
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
err = mlx5_fs_bulk_acquire_index(new_bulk, pool_index);
|
||||
WARN_ON_ONCE(err);
|
||||
list_add(&new_bulk->pool_list, &fs_pool->partially_used);
|
||||
}
|
||||
fs_pool->available_units--;
|
||||
fs_pool->used_units++;
|
||||
|
||||
out:
|
||||
mutex_unlock(&fs_pool->pool_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_fs_pool_release_index(struct mlx5_fs_pool *fs_pool,
|
||||
struct mlx5_fs_pool_index *pool_index)
|
||||
{
|
||||
struct mlx5_fs_bulk *bulk = pool_index->fs_bulk;
|
||||
int bulk_free_amount;
|
||||
int err;
|
||||
|
||||
mutex_lock(&fs_pool->pool_lock);
|
||||
|
||||
/* TBD would rather return void if there was no warn here in original code */
|
||||
err = mlx5_fs_bulk_release_index(bulk, pool_index->index);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
fs_pool->available_units++;
|
||||
fs_pool->used_units--;
|
||||
|
||||
bulk_free_amount = mlx5_fs_bulk_get_free_amount(bulk);
|
||||
if (bulk_free_amount == 1)
|
||||
list_move_tail(&bulk->pool_list, &fs_pool->partially_used);
|
||||
if (bulk_free_amount == bulk->bulk_len) {
|
||||
list_del(&bulk->pool_list);
|
||||
if (fs_pool->available_units > fs_pool->threshold)
|
||||
mlx5_fs_pool_free_bulk(fs_pool, bulk);
|
||||
else
|
||||
list_add(&bulk->pool_list, &fs_pool->unused);
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&fs_pool->pool_lock);
|
||||
return err;
|
||||
}
|
||||
54
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h
Normal file
54
drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
|
||||
|
||||
#ifndef __MLX5_FS_POOL_H__
|
||||
#define __MLX5_FS_POOL_H__
|
||||
|
||||
#include <linux/mlx5/driver.h>
|
||||
|
||||
struct mlx5_fs_bulk {
|
||||
struct list_head pool_list;
|
||||
int bulk_len;
|
||||
unsigned long *bitmask;
|
||||
};
|
||||
|
||||
struct mlx5_fs_pool_index {
|
||||
struct mlx5_fs_bulk *fs_bulk;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct mlx5_fs_pool;
|
||||
|
||||
struct mlx5_fs_pool_ops {
|
||||
int (*bulk_destroy)(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *bulk);
|
||||
struct mlx5_fs_bulk * (*bulk_create)(struct mlx5_core_dev *dev);
|
||||
void (*update_threshold)(struct mlx5_fs_pool *pool);
|
||||
};
|
||||
|
||||
struct mlx5_fs_pool {
|
||||
struct mlx5_core_dev *dev;
|
||||
void *pool_ctx;
|
||||
const struct mlx5_fs_pool_ops *ops;
|
||||
struct mutex pool_lock; /* protects pool lists */
|
||||
struct list_head fully_used;
|
||||
struct list_head partially_used;
|
||||
struct list_head unused;
|
||||
int available_units;
|
||||
int used_units;
|
||||
int threshold;
|
||||
};
|
||||
|
||||
int mlx5_fs_bulk_init(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk,
|
||||
int bulk_len);
|
||||
void mlx5_fs_bulk_cleanup(struct mlx5_fs_bulk *fs_bulk);
|
||||
int mlx5_fs_bulk_get_free_amount(struct mlx5_fs_bulk *bulk);
|
||||
|
||||
void mlx5_fs_pool_init(struct mlx5_fs_pool *pool, struct mlx5_core_dev *dev,
|
||||
const struct mlx5_fs_pool_ops *ops);
|
||||
void mlx5_fs_pool_cleanup(struct mlx5_fs_pool *pool);
|
||||
int mlx5_fs_pool_acquire_index(struct mlx5_fs_pool *fs_pool,
|
||||
struct mlx5_fs_pool_index *pool_index);
|
||||
int mlx5_fs_pool_release_index(struct mlx5_fs_pool *fs_pool,
|
||||
struct mlx5_fs_pool_index *pool_index);
|
||||
|
||||
#endif /* __MLX5_FS_POOL_H__ */
|
||||
Loading…
Reference in New Issue
Block a user