-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
net/mlx5: DR, Add modify header arg pool mechanism
Added new mechanism for handling arguments for modify-header action. The new action "accelerated modify-header" asks for the arguments from separated area from the pattern, this area accessed via general objects. Handling of these object is done via the pool-manager struct. When the new header patterns are supported, while loading the domain, a few pools for argument creations will be created. The requests for allocating/deallocating arg objects are done via the pool manager API. Signed-off-by: Muhammad Sammar <muhammads@nvidia.com> Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com> Reviewed-by: Alex Vesker <valex@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
- Loading branch information
Yevgeny Kliteynik
authored and
Saeed Mahameed
committed
Apr 14, 2023
1 parent
17dc71c
commit 608d4f1
Showing
4 changed files
with
304 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
273 changes: 273 additions & 0 deletions
273
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_arg.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB | ||
// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
|
||
#include "dr_types.h" | ||
|
||
#define DR_ICM_MODIFY_HDR_GRANULARITY_4K 12 | ||
|
||
/* modify-header arg pool */ | ||
enum dr_arg_chunk_size { | ||
DR_ARG_CHUNK_SIZE_1, | ||
DR_ARG_CHUNK_SIZE_MIN = DR_ARG_CHUNK_SIZE_1, /* keep updated when changing */ | ||
DR_ARG_CHUNK_SIZE_2, | ||
DR_ARG_CHUNK_SIZE_3, | ||
DR_ARG_CHUNK_SIZE_4, | ||
DR_ARG_CHUNK_SIZE_MAX, | ||
}; | ||
|
||
/* argument pool area */ | ||
struct dr_arg_pool { | ||
enum dr_arg_chunk_size log_chunk_size; | ||
struct mlx5dr_domain *dmn; | ||
struct list_head free_list; | ||
struct mutex mutex; /* protect arg pool */ | ||
}; | ||
|
||
struct mlx5dr_arg_mgr { | ||
struct mlx5dr_domain *dmn; | ||
struct dr_arg_pool *pools[DR_ARG_CHUNK_SIZE_MAX]; | ||
}; | ||
|
||
static int dr_arg_pool_alloc_objs(struct dr_arg_pool *pool) | ||
{ | ||
struct mlx5dr_arg_obj *arg_obj, *tmp_arg; | ||
struct list_head cur_list; | ||
u16 object_range; | ||
int num_of_objects; | ||
u32 obj_id = 0; | ||
int i, ret; | ||
|
||
INIT_LIST_HEAD(&cur_list); | ||
|
||
object_range = | ||
pool->dmn->info.caps.log_header_modify_argument_granularity; | ||
|
||
object_range = | ||
max_t(u32, pool->dmn->info.caps.log_header_modify_argument_granularity, | ||
DR_ICM_MODIFY_HDR_GRANULARITY_4K); | ||
object_range = | ||
min_t(u32, pool->dmn->info.caps.log_header_modify_argument_max_alloc, | ||
object_range); | ||
|
||
if (pool->log_chunk_size > object_range) { | ||
mlx5dr_err(pool->dmn, "Required chunk size (%d) is not supported\n", | ||
pool->log_chunk_size); | ||
return -ENOMEM; | ||
} | ||
|
||
num_of_objects = (1 << (object_range - pool->log_chunk_size)); | ||
/* Only one devx object per range */ | ||
ret = mlx5dr_cmd_create_modify_header_arg(pool->dmn->mdev, | ||
object_range, | ||
pool->dmn->pdn, | ||
&obj_id); | ||
if (ret) { | ||
mlx5dr_err(pool->dmn, "failed allocating object with range: %d:\n", | ||
object_range); | ||
return -EAGAIN; | ||
} | ||
|
||
for (i = 0; i < num_of_objects; i++) { | ||
arg_obj = kzalloc(sizeof(*arg_obj), GFP_KERNEL); | ||
if (!arg_obj) { | ||
ret = -ENOMEM; | ||
goto clean_arg_obj; | ||
} | ||
|
||
arg_obj->log_chunk_size = pool->log_chunk_size; | ||
|
||
list_add_tail(&arg_obj->list_node, &cur_list); | ||
|
||
arg_obj->obj_id = obj_id; | ||
arg_obj->obj_offset = i * (1 << pool->log_chunk_size); | ||
} | ||
list_splice_tail_init(&cur_list, &pool->free_list); | ||
|
||
return 0; | ||
|
||
clean_arg_obj: | ||
mlx5dr_cmd_destroy_modify_header_arg(pool->dmn->mdev, obj_id); | ||
list_for_each_entry_safe(arg_obj, tmp_arg, &cur_list, list_node) { | ||
list_del(&arg_obj->list_node); | ||
kfree(arg_obj); | ||
} | ||
return ret; | ||
} | ||
|
||
static struct mlx5dr_arg_obj *dr_arg_pool_get_arg_obj(struct dr_arg_pool *pool) | ||
{ | ||
struct mlx5dr_arg_obj *arg_obj = NULL; | ||
int ret; | ||
|
||
mutex_lock(&pool->mutex); | ||
if (list_empty(&pool->free_list)) { | ||
ret = dr_arg_pool_alloc_objs(pool); | ||
if (ret) | ||
goto out; | ||
} | ||
|
||
arg_obj = list_first_entry_or_null(&pool->free_list, | ||
struct mlx5dr_arg_obj, | ||
list_node); | ||
WARN(!arg_obj, "couldn't get dr arg obj from pool"); | ||
|
||
if (arg_obj) | ||
list_del_init(&arg_obj->list_node); | ||
|
||
out: | ||
mutex_unlock(&pool->mutex); | ||
return arg_obj; | ||
} | ||
|
||
static void dr_arg_pool_put_arg_obj(struct dr_arg_pool *pool, | ||
struct mlx5dr_arg_obj *arg_obj) | ||
{ | ||
mutex_lock(&pool->mutex); | ||
list_add(&arg_obj->list_node, &pool->free_list); | ||
mutex_unlock(&pool->mutex); | ||
} | ||
|
||
static struct dr_arg_pool *dr_arg_pool_create(struct mlx5dr_domain *dmn, | ||
enum dr_arg_chunk_size chunk_size) | ||
{ | ||
struct dr_arg_pool *pool; | ||
|
||
pool = kzalloc(sizeof(*pool), GFP_KERNEL); | ||
if (!pool) | ||
return NULL; | ||
|
||
pool->dmn = dmn; | ||
|
||
INIT_LIST_HEAD(&pool->free_list); | ||
mutex_init(&pool->mutex); | ||
|
||
pool->log_chunk_size = chunk_size; | ||
if (dr_arg_pool_alloc_objs(pool)) | ||
goto free_pool; | ||
|
||
return pool; | ||
|
||
free_pool: | ||
kfree(pool); | ||
|
||
return NULL; | ||
} | ||
|
||
static void dr_arg_pool_destroy(struct dr_arg_pool *pool) | ||
{ | ||
struct mlx5dr_arg_obj *arg_obj, *tmp_arg; | ||
|
||
list_for_each_entry_safe(arg_obj, tmp_arg, &pool->free_list, list_node) { | ||
list_del(&arg_obj->list_node); | ||
if (!arg_obj->obj_offset) /* the first in range */ | ||
mlx5dr_cmd_destroy_modify_header_arg(pool->dmn->mdev, arg_obj->obj_id); | ||
kfree(arg_obj); | ||
} | ||
|
||
mutex_destroy(&pool->mutex); | ||
kfree(pool); | ||
} | ||
|
||
static enum dr_arg_chunk_size dr_arg_get_chunk_size(u16 num_of_actions) | ||
{ | ||
if (num_of_actions <= 8) | ||
return DR_ARG_CHUNK_SIZE_1; | ||
if (num_of_actions <= 16) | ||
return DR_ARG_CHUNK_SIZE_2; | ||
if (num_of_actions <= 32) | ||
return DR_ARG_CHUNK_SIZE_3; | ||
if (num_of_actions <= 64) | ||
return DR_ARG_CHUNK_SIZE_4; | ||
|
||
return DR_ARG_CHUNK_SIZE_MAX; | ||
} | ||
|
||
u32 mlx5dr_arg_get_obj_id(struct mlx5dr_arg_obj *arg_obj) | ||
{ | ||
return (arg_obj->obj_id + arg_obj->obj_offset); | ||
} | ||
|
||
struct mlx5dr_arg_obj *mlx5dr_arg_get_obj(struct mlx5dr_arg_mgr *mgr, | ||
u16 num_of_actions, | ||
u8 *data) | ||
{ | ||
u32 size = dr_arg_get_chunk_size(num_of_actions); | ||
struct mlx5dr_arg_obj *arg_obj; | ||
int ret; | ||
|
||
if (size >= DR_ARG_CHUNK_SIZE_MAX) | ||
return NULL; | ||
|
||
arg_obj = dr_arg_pool_get_arg_obj(mgr->pools[size]); | ||
if (!arg_obj) { | ||
mlx5dr_err(mgr->dmn, "Failed allocating args object for modify header\n"); | ||
return NULL; | ||
} | ||
|
||
/* write it into the hw */ | ||
ret = mlx5dr_send_postsend_args(mgr->dmn, | ||
mlx5dr_arg_get_obj_id(arg_obj), | ||
num_of_actions, data); | ||
if (ret) { | ||
mlx5dr_err(mgr->dmn, "Failed writing args object\n"); | ||
goto put_obj; | ||
} | ||
|
||
return arg_obj; | ||
|
||
put_obj: | ||
mlx5dr_arg_put_obj(mgr, arg_obj); | ||
return NULL; | ||
} | ||
|
||
void mlx5dr_arg_put_obj(struct mlx5dr_arg_mgr *mgr, | ||
struct mlx5dr_arg_obj *arg_obj) | ||
{ | ||
dr_arg_pool_put_arg_obj(mgr->pools[arg_obj->log_chunk_size], arg_obj); | ||
} | ||
|
||
struct mlx5dr_arg_mgr* | ||
mlx5dr_arg_mgr_create(struct mlx5dr_domain *dmn) | ||
{ | ||
struct mlx5dr_arg_mgr *pool_mgr; | ||
int i; | ||
|
||
if (!mlx5dr_domain_is_support_ptrn_arg(dmn)) | ||
return NULL; | ||
|
||
pool_mgr = kzalloc(sizeof(*pool_mgr), GFP_KERNEL); | ||
if (!pool_mgr) | ||
return NULL; | ||
|
||
pool_mgr->dmn = dmn; | ||
|
||
for (i = 0; i < DR_ARG_CHUNK_SIZE_MAX; i++) { | ||
pool_mgr->pools[i] = dr_arg_pool_create(dmn, i); | ||
if (!pool_mgr->pools[i]) | ||
goto clean_pools; | ||
} | ||
|
||
return pool_mgr; | ||
|
||
clean_pools: | ||
for (i--; i >= 0; i--) | ||
dr_arg_pool_destroy(pool_mgr->pools[i]); | ||
|
||
kfree(pool_mgr); | ||
return NULL; | ||
} | ||
|
||
void mlx5dr_arg_mgr_destroy(struct mlx5dr_arg_mgr *mgr) | ||
{ | ||
struct dr_arg_pool **pools; | ||
int i; | ||
|
||
if (!mgr) | ||
return; | ||
|
||
pools = mgr->pools; | ||
for (i = 0; i < DR_ARG_CHUNK_SIZE_MAX; i++) | ||
dr_arg_pool_destroy(pools[i]); | ||
|
||
kfree(mgr); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters