1f8c8a6d8SErez Shitrit /* SPDX-License-Identifier: BSD-3-Clause
2f8c8a6d8SErez Shitrit * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3f8c8a6d8SErez Shitrit */
4f8c8a6d8SErez Shitrit
5f8c8a6d8SErez Shitrit #include "mlx5dr_internal.h"
6f8c8a6d8SErez Shitrit
7f8c8a6d8SErez Shitrit enum mlx5dr_arg_chunk_size
mlx5dr_arg_data_size_to_arg_log_size(uint16_t data_size)8f8c8a6d8SErez Shitrit mlx5dr_arg_data_size_to_arg_log_size(uint16_t data_size)
9f8c8a6d8SErez Shitrit {
10f8c8a6d8SErez Shitrit /* Return the roundup of log2(data_size) */
11f8c8a6d8SErez Shitrit if (data_size <= MLX5DR_ARG_DATA_SIZE)
12f8c8a6d8SErez Shitrit return MLX5DR_ARG_CHUNK_SIZE_1;
13f8c8a6d8SErez Shitrit if (data_size <= MLX5DR_ARG_DATA_SIZE * 2)
14f8c8a6d8SErez Shitrit return MLX5DR_ARG_CHUNK_SIZE_2;
15f8c8a6d8SErez Shitrit if (data_size <= MLX5DR_ARG_DATA_SIZE * 4)
16f8c8a6d8SErez Shitrit return MLX5DR_ARG_CHUNK_SIZE_3;
17f8c8a6d8SErez Shitrit if (data_size <= MLX5DR_ARG_DATA_SIZE * 8)
18f8c8a6d8SErez Shitrit return MLX5DR_ARG_CHUNK_SIZE_4;
19f8c8a6d8SErez Shitrit
20f8c8a6d8SErez Shitrit return MLX5DR_ARG_CHUNK_SIZE_MAX;
21f8c8a6d8SErez Shitrit }
22f8c8a6d8SErez Shitrit
mlx5dr_arg_data_size_to_arg_size(uint16_t data_size)23f8c8a6d8SErez Shitrit uint32_t mlx5dr_arg_data_size_to_arg_size(uint16_t data_size)
24f8c8a6d8SErez Shitrit {
25f8c8a6d8SErez Shitrit return BIT(mlx5dr_arg_data_size_to_arg_log_size(data_size));
26f8c8a6d8SErez Shitrit }
27f8c8a6d8SErez Shitrit
28f8c8a6d8SErez Shitrit enum mlx5dr_arg_chunk_size
mlx5dr_arg_get_arg_log_size(uint16_t num_of_actions)29f8c8a6d8SErez Shitrit mlx5dr_arg_get_arg_log_size(uint16_t num_of_actions)
30f8c8a6d8SErez Shitrit {
31f8c8a6d8SErez Shitrit return mlx5dr_arg_data_size_to_arg_log_size(num_of_actions *
32f8c8a6d8SErez Shitrit MLX5DR_MODIFY_ACTION_SIZE);
33f8c8a6d8SErez Shitrit }
34f8c8a6d8SErez Shitrit
mlx5dr_arg_get_arg_size(uint16_t num_of_actions)35f8c8a6d8SErez Shitrit uint32_t mlx5dr_arg_get_arg_size(uint16_t num_of_actions)
36f8c8a6d8SErez Shitrit {
37f8c8a6d8SErez Shitrit return BIT(mlx5dr_arg_get_arg_log_size(num_of_actions));
38f8c8a6d8SErez Shitrit }
39f8c8a6d8SErez Shitrit
mlx5dr_pat_require_reparse(__be64 * actions,uint16_t num_of_actions)40274e17f7SAlex Vesker bool mlx5dr_pat_require_reparse(__be64 *actions, uint16_t num_of_actions)
41274e17f7SAlex Vesker {
42274e17f7SAlex Vesker uint16_t i, field;
43274e17f7SAlex Vesker uint8_t action_id;
44274e17f7SAlex Vesker
45274e17f7SAlex Vesker for (i = 0; i < num_of_actions; i++) {
46274e17f7SAlex Vesker action_id = MLX5_GET(set_action_in, &actions[i], action_type);
47274e17f7SAlex Vesker
48274e17f7SAlex Vesker switch (action_id) {
49274e17f7SAlex Vesker case MLX5_MODIFICATION_TYPE_NOP:
50274e17f7SAlex Vesker field = MLX5_MODI_OUT_NONE;
51274e17f7SAlex Vesker break;
52274e17f7SAlex Vesker
53274e17f7SAlex Vesker case MLX5_MODIFICATION_TYPE_SET:
54274e17f7SAlex Vesker case MLX5_MODIFICATION_TYPE_ADD:
55274e17f7SAlex Vesker field = MLX5_GET(set_action_in, &actions[i], field);
56274e17f7SAlex Vesker break;
57274e17f7SAlex Vesker
58274e17f7SAlex Vesker case MLX5_MODIFICATION_TYPE_COPY:
59274e17f7SAlex Vesker case MLX5_MODIFICATION_TYPE_ADD_FIELD:
60274e17f7SAlex Vesker field = MLX5_GET(copy_action_in, &actions[i], dst_field);
61274e17f7SAlex Vesker break;
62274e17f7SAlex Vesker
63274e17f7SAlex Vesker default:
64274e17f7SAlex Vesker /* Insert/Remove/Unknown actions require reparse */
65274e17f7SAlex Vesker return true;
66274e17f7SAlex Vesker }
67274e17f7SAlex Vesker
68274e17f7SAlex Vesker /* Below fields can change packet structure require a reparse */
69274e17f7SAlex Vesker if (field == MLX5_MODI_OUT_ETHERTYPE ||
70*c9b52e98SMichael Baum field == MLX5_MODI_OUT_IP_PROTOCOL)
71274e17f7SAlex Vesker return true;
72274e17f7SAlex Vesker }
73274e17f7SAlex Vesker
74274e17f7SAlex Vesker return false;
75274e17f7SAlex Vesker }
76274e17f7SAlex Vesker
77f8c8a6d8SErez Shitrit /* Cache and cache element handling */
mlx5dr_pat_init_pattern_cache(struct mlx5dr_pattern_cache ** cache)78f8c8a6d8SErez Shitrit int mlx5dr_pat_init_pattern_cache(struct mlx5dr_pattern_cache **cache)
79f8c8a6d8SErez Shitrit {
80f8c8a6d8SErez Shitrit struct mlx5dr_pattern_cache *new_cache;
81f8c8a6d8SErez Shitrit
82f8c8a6d8SErez Shitrit new_cache = simple_calloc(1, sizeof(*new_cache));
83f8c8a6d8SErez Shitrit if (!new_cache) {
84f8c8a6d8SErez Shitrit rte_errno = ENOMEM;
85f8c8a6d8SErez Shitrit return rte_errno;
86f8c8a6d8SErez Shitrit }
87f8c8a6d8SErez Shitrit LIST_INIT(&new_cache->head);
88f8c8a6d8SErez Shitrit pthread_spin_init(&new_cache->lock, PTHREAD_PROCESS_PRIVATE);
89f8c8a6d8SErez Shitrit
90f8c8a6d8SErez Shitrit *cache = new_cache;
91f8c8a6d8SErez Shitrit
92f8c8a6d8SErez Shitrit return 0;
93f8c8a6d8SErez Shitrit }
94f8c8a6d8SErez Shitrit
mlx5dr_pat_uninit_pattern_cache(struct mlx5dr_pattern_cache * cache)95f8c8a6d8SErez Shitrit void mlx5dr_pat_uninit_pattern_cache(struct mlx5dr_pattern_cache *cache)
96f8c8a6d8SErez Shitrit {
97f8c8a6d8SErez Shitrit simple_free(cache);
98f8c8a6d8SErez Shitrit }
99f8c8a6d8SErez Shitrit
mlx5dr_pat_compare_pattern(int cur_num_of_actions,__be64 cur_actions[],int num_of_actions,__be64 actions[])1003a6c5021SAlex Vesker static bool mlx5dr_pat_compare_pattern(int cur_num_of_actions,
101f8c8a6d8SErez Shitrit __be64 cur_actions[],
102f8c8a6d8SErez Shitrit int num_of_actions,
103f8c8a6d8SErez Shitrit __be64 actions[])
104f8c8a6d8SErez Shitrit {
105f8c8a6d8SErez Shitrit int i;
106f8c8a6d8SErez Shitrit
1073a6c5021SAlex Vesker if (cur_num_of_actions != num_of_actions)
108f8c8a6d8SErez Shitrit return false;
109f8c8a6d8SErez Shitrit
110f8c8a6d8SErez Shitrit for (i = 0; i < num_of_actions; i++) {
111f8c8a6d8SErez Shitrit u8 action_id =
112f8c8a6d8SErez Shitrit MLX5_GET(set_action_in, &actions[i], action_type);
113f8c8a6d8SErez Shitrit
1141667b1d7SItamar Gozlan if (action_id == MLX5_MODIFICATION_TYPE_COPY ||
1151667b1d7SItamar Gozlan action_id == MLX5_MODIFICATION_TYPE_ADD_FIELD) {
116f8c8a6d8SErez Shitrit if (actions[i] != cur_actions[i])
117f8c8a6d8SErez Shitrit return false;
118f8c8a6d8SErez Shitrit } else {
119f8c8a6d8SErez Shitrit /* Compare just the control, not the values */
120f8c8a6d8SErez Shitrit if ((__be32)actions[i] !=
121f8c8a6d8SErez Shitrit (__be32)cur_actions[i])
122f8c8a6d8SErez Shitrit return false;
123f8c8a6d8SErez Shitrit }
124f8c8a6d8SErez Shitrit }
125f8c8a6d8SErez Shitrit
126f8c8a6d8SErez Shitrit return true;
127f8c8a6d8SErez Shitrit }
128f8c8a6d8SErez Shitrit
129e4a3e90bSAlex Vesker static struct mlx5dr_pattern_cache_item *
mlx5dr_pat_find_cached_pattern(struct mlx5dr_pattern_cache * cache,uint16_t num_of_actions,__be64 * actions)130f8c8a6d8SErez Shitrit mlx5dr_pat_find_cached_pattern(struct mlx5dr_pattern_cache *cache,
131f8c8a6d8SErez Shitrit uint16_t num_of_actions,
132f8c8a6d8SErez Shitrit __be64 *actions)
133f8c8a6d8SErez Shitrit {
134e4a3e90bSAlex Vesker struct mlx5dr_pattern_cache_item *cached_pat;
135f8c8a6d8SErez Shitrit
136f8c8a6d8SErez Shitrit LIST_FOREACH(cached_pat, &cache->head, next) {
1373a6c5021SAlex Vesker if (mlx5dr_pat_compare_pattern(cached_pat->mh_data.num_of_actions,
138f8c8a6d8SErez Shitrit (__be64 *)cached_pat->mh_data.data,
139f8c8a6d8SErez Shitrit num_of_actions,
140f8c8a6d8SErez Shitrit actions))
141f8c8a6d8SErez Shitrit return cached_pat;
142f8c8a6d8SErez Shitrit }
143f8c8a6d8SErez Shitrit
144f8c8a6d8SErez Shitrit return NULL;
145f8c8a6d8SErez Shitrit }
146f8c8a6d8SErez Shitrit
147e4a3e90bSAlex Vesker static struct mlx5dr_pattern_cache_item *
mlx5dr_pat_get_existing_cached_pattern(struct mlx5dr_pattern_cache * cache,uint16_t num_of_actions,__be64 * actions)148f8c8a6d8SErez Shitrit mlx5dr_pat_get_existing_cached_pattern(struct mlx5dr_pattern_cache *cache,
149f8c8a6d8SErez Shitrit uint16_t num_of_actions,
150f8c8a6d8SErez Shitrit __be64 *actions)
151f8c8a6d8SErez Shitrit {
152e4a3e90bSAlex Vesker struct mlx5dr_pattern_cache_item *cached_pattern;
153f8c8a6d8SErez Shitrit
1543a6c5021SAlex Vesker cached_pattern = mlx5dr_pat_find_cached_pattern(cache, num_of_actions, actions);
155f8c8a6d8SErez Shitrit if (cached_pattern) {
156f8c8a6d8SErez Shitrit /* LRU: move it to be first in the list */
157f8c8a6d8SErez Shitrit LIST_REMOVE(cached_pattern, next);
158f8c8a6d8SErez Shitrit LIST_INSERT_HEAD(&cache->head, cached_pattern, next);
1590bed4ef7SAlex Vesker cached_pattern->refcount++;
160f8c8a6d8SErez Shitrit }
161f8c8a6d8SErez Shitrit
162f8c8a6d8SErez Shitrit return cached_pattern;
163f8c8a6d8SErez Shitrit }
164f8c8a6d8SErez Shitrit
165e4a3e90bSAlex Vesker static struct mlx5dr_pattern_cache_item *
mlx5dr_pat_add_pattern_to_cache(struct mlx5dr_pattern_cache * cache,struct mlx5dr_devx_obj * pattern_obj,uint16_t num_of_actions,__be64 * actions)166f8c8a6d8SErez Shitrit mlx5dr_pat_add_pattern_to_cache(struct mlx5dr_pattern_cache *cache,
167f8c8a6d8SErez Shitrit struct mlx5dr_devx_obj *pattern_obj,
168f8c8a6d8SErez Shitrit uint16_t num_of_actions,
169f8c8a6d8SErez Shitrit __be64 *actions)
170f8c8a6d8SErez Shitrit {
171e4a3e90bSAlex Vesker struct mlx5dr_pattern_cache_item *cached_pattern;
172f8c8a6d8SErez Shitrit
173f8c8a6d8SErez Shitrit cached_pattern = simple_calloc(1, sizeof(*cached_pattern));
174f8c8a6d8SErez Shitrit if (!cached_pattern) {
175f8c8a6d8SErez Shitrit DR_LOG(ERR, "Failed to allocate cached_pattern");
176f8c8a6d8SErez Shitrit rte_errno = ENOMEM;
177f8c8a6d8SErez Shitrit return NULL;
178f8c8a6d8SErez Shitrit }
179f8c8a6d8SErez Shitrit
180f8c8a6d8SErez Shitrit cached_pattern->mh_data.num_of_actions = num_of_actions;
181f8c8a6d8SErez Shitrit cached_pattern->mh_data.pattern_obj = pattern_obj;
182f8c8a6d8SErez Shitrit cached_pattern->mh_data.data =
183f8c8a6d8SErez Shitrit simple_malloc(num_of_actions * MLX5DR_MODIFY_ACTION_SIZE);
184f8c8a6d8SErez Shitrit if (!cached_pattern->mh_data.data) {
185f8c8a6d8SErez Shitrit DR_LOG(ERR, "Failed to allocate mh_data.data");
186f8c8a6d8SErez Shitrit rte_errno = ENOMEM;
187f8c8a6d8SErez Shitrit goto free_cached_obj;
188f8c8a6d8SErez Shitrit }
189f8c8a6d8SErez Shitrit
190f8c8a6d8SErez Shitrit memcpy(cached_pattern->mh_data.data, actions,
191f8c8a6d8SErez Shitrit num_of_actions * MLX5DR_MODIFY_ACTION_SIZE);
192f8c8a6d8SErez Shitrit
193f8c8a6d8SErez Shitrit LIST_INSERT_HEAD(&cache->head, cached_pattern, next);
1940bed4ef7SAlex Vesker cached_pattern->refcount = 1;
195f8c8a6d8SErez Shitrit
196f8c8a6d8SErez Shitrit return cached_pattern;
197f8c8a6d8SErez Shitrit
198f8c8a6d8SErez Shitrit free_cached_obj:
199f8c8a6d8SErez Shitrit simple_free(cached_pattern);
200f8c8a6d8SErez Shitrit return NULL;
201f8c8a6d8SErez Shitrit }
202f8c8a6d8SErez Shitrit
2033a6c5021SAlex Vesker static struct mlx5dr_pattern_cache_item *
mlx5dr_pat_find_cached_pattern_by_obj(struct mlx5dr_pattern_cache * cache,struct mlx5dr_devx_obj * pat_obj)2043a6c5021SAlex Vesker mlx5dr_pat_find_cached_pattern_by_obj(struct mlx5dr_pattern_cache *cache,
2053a6c5021SAlex Vesker struct mlx5dr_devx_obj *pat_obj)
2063a6c5021SAlex Vesker {
2073a6c5021SAlex Vesker struct mlx5dr_pattern_cache_item *cached_pattern;
2083a6c5021SAlex Vesker
2093a6c5021SAlex Vesker LIST_FOREACH(cached_pattern, &cache->head, next) {
2103a6c5021SAlex Vesker if (cached_pattern->mh_data.pattern_obj->id == pat_obj->id)
2113a6c5021SAlex Vesker return cached_pattern;
2123a6c5021SAlex Vesker }
2133a6c5021SAlex Vesker
2143a6c5021SAlex Vesker return NULL;
2153a6c5021SAlex Vesker }
2163a6c5021SAlex Vesker
217f8c8a6d8SErez Shitrit static void
mlx5dr_pat_remove_pattern(struct mlx5dr_pattern_cache_item * cached_pattern)218e4a3e90bSAlex Vesker mlx5dr_pat_remove_pattern(struct mlx5dr_pattern_cache_item *cached_pattern)
219f8c8a6d8SErez Shitrit {
220f8c8a6d8SErez Shitrit LIST_REMOVE(cached_pattern, next);
221f8c8a6d8SErez Shitrit simple_free(cached_pattern->mh_data.data);
222f8c8a6d8SErez Shitrit simple_free(cached_pattern);
223f8c8a6d8SErez Shitrit }
224f8c8a6d8SErez Shitrit
mlx5dr_pat_put_pattern(struct mlx5dr_context * ctx,struct mlx5dr_devx_obj * pat_obj)2253a6c5021SAlex Vesker void mlx5dr_pat_put_pattern(struct mlx5dr_context *ctx,
2263a6c5021SAlex Vesker struct mlx5dr_devx_obj *pat_obj)
227f8c8a6d8SErez Shitrit {
2283a6c5021SAlex Vesker struct mlx5dr_pattern_cache *cache = ctx->pattern_cache;
229e4a3e90bSAlex Vesker struct mlx5dr_pattern_cache_item *cached_pattern;
230f8c8a6d8SErez Shitrit
231f8c8a6d8SErez Shitrit pthread_spin_lock(&cache->lock);
2323a6c5021SAlex Vesker cached_pattern = mlx5dr_pat_find_cached_pattern_by_obj(cache, pat_obj);
233f8c8a6d8SErez Shitrit if (!cached_pattern) {
234f8c8a6d8SErez Shitrit DR_LOG(ERR, "Failed to find pattern according to action with pt");
235f8c8a6d8SErez Shitrit assert(false);
236f8c8a6d8SErez Shitrit goto out;
237f8c8a6d8SErez Shitrit }
238f8c8a6d8SErez Shitrit
2390bed4ef7SAlex Vesker if (--cached_pattern->refcount)
240f8c8a6d8SErez Shitrit goto out;
241f8c8a6d8SErez Shitrit
242f8c8a6d8SErez Shitrit mlx5dr_pat_remove_pattern(cached_pattern);
2433a6c5021SAlex Vesker mlx5dr_cmd_destroy_obj(pat_obj);
244f8c8a6d8SErez Shitrit
245f8c8a6d8SErez Shitrit out:
246f8c8a6d8SErez Shitrit pthread_spin_unlock(&cache->lock);
247f8c8a6d8SErez Shitrit }
248f8c8a6d8SErez Shitrit
2493a6c5021SAlex Vesker struct mlx5dr_devx_obj *
mlx5dr_pat_get_pattern(struct mlx5dr_context * ctx,__be64 * pattern,size_t pattern_sz)2503a6c5021SAlex Vesker mlx5dr_pat_get_pattern(struct mlx5dr_context *ctx,
2513a6c5021SAlex Vesker __be64 *pattern, size_t pattern_sz)
252f8c8a6d8SErez Shitrit {
2533a6c5021SAlex Vesker uint16_t num_of_actions = pattern_sz / MLX5DR_MODIFY_ACTION_SIZE;
254e4a3e90bSAlex Vesker struct mlx5dr_pattern_cache_item *cached_pattern;
2553a6c5021SAlex Vesker struct mlx5dr_devx_obj *pat_obj = NULL;
256f8c8a6d8SErez Shitrit
257f8c8a6d8SErez Shitrit pthread_spin_lock(&ctx->pattern_cache->lock);
258f8c8a6d8SErez Shitrit
259f8c8a6d8SErez Shitrit cached_pattern = mlx5dr_pat_get_existing_cached_pattern(ctx->pattern_cache,
260f8c8a6d8SErez Shitrit num_of_actions,
261f8c8a6d8SErez Shitrit pattern);
262f8c8a6d8SErez Shitrit if (cached_pattern) {
2633a6c5021SAlex Vesker pat_obj = cached_pattern->mh_data.pattern_obj;
264f8c8a6d8SErez Shitrit goto out_unlock;
265f8c8a6d8SErez Shitrit }
266f8c8a6d8SErez Shitrit
2673a6c5021SAlex Vesker pat_obj = mlx5dr_cmd_header_modify_pattern_create(ctx->ibv_ctx,
268f8c8a6d8SErez Shitrit pattern_sz,
269f8c8a6d8SErez Shitrit (uint8_t *)pattern);
2703a6c5021SAlex Vesker if (!pat_obj) {
271f8c8a6d8SErez Shitrit DR_LOG(ERR, "Failed to create pattern FW object");
272f8c8a6d8SErez Shitrit goto out_unlock;
273f8c8a6d8SErez Shitrit }
274f8c8a6d8SErez Shitrit
2753a6c5021SAlex Vesker cached_pattern = mlx5dr_pat_add_pattern_to_cache(ctx->pattern_cache,
2763a6c5021SAlex Vesker pat_obj,
277f8c8a6d8SErez Shitrit num_of_actions,
278f8c8a6d8SErez Shitrit pattern);
279f8c8a6d8SErez Shitrit if (!cached_pattern) {
280f8c8a6d8SErez Shitrit DR_LOG(ERR, "Failed to add pattern to cache");
281f8c8a6d8SErez Shitrit goto clean_pattern;
282f8c8a6d8SErez Shitrit }
283f8c8a6d8SErez Shitrit
284f8c8a6d8SErez Shitrit pthread_spin_unlock(&ctx->pattern_cache->lock);
2853a6c5021SAlex Vesker return pat_obj;
286f8c8a6d8SErez Shitrit
287f8c8a6d8SErez Shitrit clean_pattern:
2883a6c5021SAlex Vesker mlx5dr_cmd_destroy_obj(pat_obj);
2893a6c5021SAlex Vesker pat_obj = NULL;
2903a6c5021SAlex Vesker out_unlock:
291f8c8a6d8SErez Shitrit pthread_spin_unlock(&ctx->pattern_cache->lock);
2923a6c5021SAlex Vesker return pat_obj;
293f8c8a6d8SErez Shitrit }
294f8c8a6d8SErez Shitrit
295f8c8a6d8SErez Shitrit static void
mlx5d_arg_init_send_attr(struct mlx5dr_send_engine_post_attr * send_attr,void * comp_data,uint32_t arg_idx)296f8c8a6d8SErez Shitrit mlx5d_arg_init_send_attr(struct mlx5dr_send_engine_post_attr *send_attr,
297f8c8a6d8SErez Shitrit void *comp_data,
298f8c8a6d8SErez Shitrit uint32_t arg_idx)
299f8c8a6d8SErez Shitrit {
300f8c8a6d8SErez Shitrit send_attr->opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
301f8c8a6d8SErez Shitrit send_attr->opmod = MLX5DR_WQE_GTA_OPMOD_MOD_ARG;
302f8c8a6d8SErez Shitrit send_attr->len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
303f8c8a6d8SErez Shitrit send_attr->id = arg_idx;
304f8c8a6d8SErez Shitrit send_attr->user_data = comp_data;
305f8c8a6d8SErez Shitrit }
306f8c8a6d8SErez Shitrit
mlx5dr_arg_decapl3_write(struct mlx5dr_send_engine * queue,uint32_t arg_idx,uint8_t * arg_data,uint16_t num_of_actions)307f8c8a6d8SErez Shitrit void mlx5dr_arg_decapl3_write(struct mlx5dr_send_engine *queue,
308f8c8a6d8SErez Shitrit uint32_t arg_idx,
309f8c8a6d8SErez Shitrit uint8_t *arg_data,
310f8c8a6d8SErez Shitrit uint16_t num_of_actions)
311f8c8a6d8SErez Shitrit {
312f8c8a6d8SErez Shitrit struct mlx5dr_send_engine_post_attr send_attr = {0};
313f8c8a6d8SErez Shitrit struct mlx5dr_wqe_gta_data_seg_arg *wqe_arg;
314f8c8a6d8SErez Shitrit struct mlx5dr_send_engine_post_ctrl ctrl;
315f8c8a6d8SErez Shitrit struct mlx5dr_wqe_gta_ctrl_seg *wqe_ctrl;
316f8c8a6d8SErez Shitrit size_t wqe_len;
317f8c8a6d8SErez Shitrit
318f8c8a6d8SErez Shitrit mlx5d_arg_init_send_attr(&send_attr, NULL, arg_idx);
319f8c8a6d8SErez Shitrit
320f8c8a6d8SErez Shitrit ctrl = mlx5dr_send_engine_post_start(queue);
321f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
322f8c8a6d8SErez Shitrit memset(wqe_ctrl, 0, wqe_len);
323f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_arg, &wqe_len);
324f8c8a6d8SErez Shitrit mlx5dr_action_prepare_decap_l3_data(arg_data, (uint8_t *)wqe_arg,
325f8c8a6d8SErez Shitrit num_of_actions);
326f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_end(&ctrl, &send_attr);
327f8c8a6d8SErez Shitrit }
328f8c8a6d8SErez Shitrit
mlx5dr_arg_write(struct mlx5dr_send_engine * queue,void * comp_data,uint32_t arg_idx,uint8_t * arg_data,size_t data_size)329f8c8a6d8SErez Shitrit void mlx5dr_arg_write(struct mlx5dr_send_engine *queue,
330f8c8a6d8SErez Shitrit void *comp_data,
331f8c8a6d8SErez Shitrit uint32_t arg_idx,
332f8c8a6d8SErez Shitrit uint8_t *arg_data,
333f8c8a6d8SErez Shitrit size_t data_size)
334f8c8a6d8SErez Shitrit {
335f8c8a6d8SErez Shitrit struct mlx5dr_send_engine_post_attr send_attr = {0};
336f8c8a6d8SErez Shitrit struct mlx5dr_wqe_gta_data_seg_arg *wqe_arg;
337f8c8a6d8SErez Shitrit struct mlx5dr_send_engine_post_ctrl ctrl;
338f8c8a6d8SErez Shitrit struct mlx5dr_wqe_gta_ctrl_seg *wqe_ctrl;
339f8c8a6d8SErez Shitrit int i, full_iter, leftover;
340f8c8a6d8SErez Shitrit size_t wqe_len;
341f8c8a6d8SErez Shitrit
342f8c8a6d8SErez Shitrit mlx5d_arg_init_send_attr(&send_attr, comp_data, arg_idx);
343f8c8a6d8SErez Shitrit
344f8c8a6d8SErez Shitrit /* Each WQE can hold 64B of data, it might require multiple iteration */
345f8c8a6d8SErez Shitrit full_iter = data_size / MLX5DR_ARG_DATA_SIZE;
346f8c8a6d8SErez Shitrit leftover = data_size & (MLX5DR_ARG_DATA_SIZE - 1);
347f8c8a6d8SErez Shitrit
348f8c8a6d8SErez Shitrit for (i = 0; i < full_iter; i++) {
349f8c8a6d8SErez Shitrit ctrl = mlx5dr_send_engine_post_start(queue);
350f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
351f8c8a6d8SErez Shitrit memset(wqe_ctrl, 0, wqe_len);
352f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_arg, &wqe_len);
353f8c8a6d8SErez Shitrit memcpy(wqe_arg, arg_data, wqe_len);
354f8c8a6d8SErez Shitrit send_attr.id = arg_idx++;
355f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_end(&ctrl, &send_attr);
356f8c8a6d8SErez Shitrit
357f8c8a6d8SErez Shitrit /* Move to next argument data */
358f8c8a6d8SErez Shitrit arg_data += MLX5DR_ARG_DATA_SIZE;
359f8c8a6d8SErez Shitrit }
360f8c8a6d8SErez Shitrit
361f8c8a6d8SErez Shitrit if (leftover) {
362f8c8a6d8SErez Shitrit ctrl = mlx5dr_send_engine_post_start(queue);
363f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
364f8c8a6d8SErez Shitrit memset(wqe_ctrl, 0, wqe_len);
365f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_req_wqe(&ctrl, (void *)&wqe_arg, &wqe_len);
366f8c8a6d8SErez Shitrit memcpy(wqe_arg, arg_data, leftover);
367f8c8a6d8SErez Shitrit send_attr.id = arg_idx;
368f8c8a6d8SErez Shitrit mlx5dr_send_engine_post_end(&ctrl, &send_attr);
369f8c8a6d8SErez Shitrit }
370f8c8a6d8SErez Shitrit }
371f8c8a6d8SErez Shitrit
mlx5dr_arg_write_inline_arg_data(struct mlx5dr_context * ctx,uint32_t arg_idx,uint8_t * arg_data,size_t data_size)372f8c8a6d8SErez Shitrit int mlx5dr_arg_write_inline_arg_data(struct mlx5dr_context *ctx,
373f8c8a6d8SErez Shitrit uint32_t arg_idx,
374f8c8a6d8SErez Shitrit uint8_t *arg_data,
375f8c8a6d8SErez Shitrit size_t data_size)
376f8c8a6d8SErez Shitrit {
377f8c8a6d8SErez Shitrit struct mlx5dr_send_engine *queue;
378f8c8a6d8SErez Shitrit int ret;
379f8c8a6d8SErez Shitrit
380f8c8a6d8SErez Shitrit pthread_spin_lock(&ctx->ctrl_lock);
381f8c8a6d8SErez Shitrit
382f8c8a6d8SErez Shitrit /* Get the control queue */
383f8c8a6d8SErez Shitrit queue = &ctx->send_queue[ctx->queues - 1];
384f8c8a6d8SErez Shitrit
385f8c8a6d8SErez Shitrit mlx5dr_arg_write(queue, arg_data, arg_idx, arg_data, data_size);
386f8c8a6d8SErez Shitrit
387f8c8a6d8SErez Shitrit mlx5dr_send_engine_flush_queue(queue);
388f8c8a6d8SErez Shitrit
389f8c8a6d8SErez Shitrit /* Poll for completion */
39090488887SAlex Vesker ret = mlx5dr_send_queue_action(ctx, ctx->queues - 1,
39190488887SAlex Vesker MLX5DR_SEND_QUEUE_ACTION_DRAIN_SYNC);
39290488887SAlex Vesker
393f8c8a6d8SErez Shitrit if (ret)
39490488887SAlex Vesker DR_LOG(ERR, "Failed to drain arg queue");
395f8c8a6d8SErez Shitrit
396f8c8a6d8SErez Shitrit pthread_spin_unlock(&ctx->ctrl_lock);
397f8c8a6d8SErez Shitrit
398f8c8a6d8SErez Shitrit return ret;
399f8c8a6d8SErez Shitrit }
400f8c8a6d8SErez Shitrit
mlx5dr_arg_is_valid_arg_request_size(struct mlx5dr_context * ctx,uint32_t arg_size)401f8c8a6d8SErez Shitrit bool mlx5dr_arg_is_valid_arg_request_size(struct mlx5dr_context *ctx,
402f8c8a6d8SErez Shitrit uint32_t arg_size)
403f8c8a6d8SErez Shitrit {
404f8c8a6d8SErez Shitrit if (arg_size < ctx->caps->log_header_modify_argument_granularity ||
405f8c8a6d8SErez Shitrit arg_size > ctx->caps->log_header_modify_argument_max_alloc) {
406f8c8a6d8SErez Shitrit return false;
407f8c8a6d8SErez Shitrit }
408f8c8a6d8SErez Shitrit return true;
409f8c8a6d8SErez Shitrit }
410f8c8a6d8SErez Shitrit
4113a6c5021SAlex Vesker struct mlx5dr_devx_obj *
mlx5dr_arg_create(struct mlx5dr_context * ctx,uint8_t * data,size_t data_sz,uint32_t log_bulk_sz,bool write_data)4123a6c5021SAlex Vesker mlx5dr_arg_create(struct mlx5dr_context *ctx,
4133a6c5021SAlex Vesker uint8_t *data,
4143a6c5021SAlex Vesker size_t data_sz,
4153a6c5021SAlex Vesker uint32_t log_bulk_sz,
4163a6c5021SAlex Vesker bool write_data)
417f8c8a6d8SErez Shitrit {
4183a6c5021SAlex Vesker struct mlx5dr_devx_obj *arg_obj;
4193a6c5021SAlex Vesker uint16_t single_arg_log_sz;
4203a6c5021SAlex Vesker uint16_t multi_arg_log_sz;
4213a6c5021SAlex Vesker int ret;
4223a6c5021SAlex Vesker
4233a6c5021SAlex Vesker single_arg_log_sz = mlx5dr_arg_data_size_to_arg_log_size(data_sz);
4243a6c5021SAlex Vesker multi_arg_log_sz = single_arg_log_sz + log_bulk_sz;
4253a6c5021SAlex Vesker
4263a6c5021SAlex Vesker if (single_arg_log_sz >= MLX5DR_ARG_CHUNK_SIZE_MAX) {
4273a6c5021SAlex Vesker DR_LOG(ERR, "Requested single arg %u not supported", single_arg_log_sz);
4283a6c5021SAlex Vesker rte_errno = ENOTSUP;
4293a6c5021SAlex Vesker return NULL;
4303a6c5021SAlex Vesker }
4313a6c5021SAlex Vesker
4323a6c5021SAlex Vesker if (!mlx5dr_arg_is_valid_arg_request_size(ctx, multi_arg_log_sz)) {
4333a6c5021SAlex Vesker DR_LOG(ERR, "Argument log size %d not supported by FW", multi_arg_log_sz);
4343a6c5021SAlex Vesker rte_errno = ENOTSUP;
4353a6c5021SAlex Vesker return NULL;
4363a6c5021SAlex Vesker }
437f8c8a6d8SErez Shitrit
438f8c8a6d8SErez Shitrit /* Alloc bulk of args */
4393a6c5021SAlex Vesker arg_obj = mlx5dr_cmd_arg_create(ctx->ibv_ctx, multi_arg_log_sz, ctx->pd_num);
4403a6c5021SAlex Vesker if (!arg_obj) {
4413a6c5021SAlex Vesker DR_LOG(ERR, "Failed allocating arg in order: %d", multi_arg_log_sz);
4423a6c5021SAlex Vesker return NULL;
443f8c8a6d8SErez Shitrit }
444f8c8a6d8SErez Shitrit
4453a6c5021SAlex Vesker if (write_data) {
446f8c8a6d8SErez Shitrit ret = mlx5dr_arg_write_inline_arg_data(ctx,
4473a6c5021SAlex Vesker arg_obj->id,
4483a6c5021SAlex Vesker data, data_sz);
449f8c8a6d8SErez Shitrit if (ret) {
4503a6c5021SAlex Vesker DR_LOG(ERR, "Failed writing arg data");
4513a6c5021SAlex Vesker mlx5dr_cmd_destroy_obj(arg_obj);
4523a6c5021SAlex Vesker return NULL;
4533a6c5021SAlex Vesker }
454f8c8a6d8SErez Shitrit }
455f8c8a6d8SErez Shitrit
4563a6c5021SAlex Vesker return arg_obj;
457f8c8a6d8SErez Shitrit }
458f8c8a6d8SErez Shitrit
4593a6c5021SAlex Vesker struct mlx5dr_devx_obj *
mlx5dr_arg_create_modify_header_arg(struct mlx5dr_context * ctx,__be64 * data,uint8_t num_of_actions,uint32_t log_bulk_sz,bool write_data)4603a6c5021SAlex Vesker mlx5dr_arg_create_modify_header_arg(struct mlx5dr_context *ctx,
4613a6c5021SAlex Vesker __be64 *data,
4623a6c5021SAlex Vesker uint8_t num_of_actions,
4633a6c5021SAlex Vesker uint32_t log_bulk_sz,
4643a6c5021SAlex Vesker bool write_data)
465102e59c2SErez Shitrit {
4663a6c5021SAlex Vesker size_t data_sz = num_of_actions * MLX5DR_MODIFY_ACTION_SIZE;
4673a6c5021SAlex Vesker struct mlx5dr_devx_obj *arg_obj;
468102e59c2SErez Shitrit
4693a6c5021SAlex Vesker arg_obj = mlx5dr_arg_create(ctx,
4703a6c5021SAlex Vesker (uint8_t *)data,
4713a6c5021SAlex Vesker data_sz,
4723a6c5021SAlex Vesker log_bulk_sz,
4733a6c5021SAlex Vesker write_data);
4743a6c5021SAlex Vesker if (!arg_obj)
4753a6c5021SAlex Vesker DR_LOG(ERR, "Failed creating modify header arg");
4763a6c5021SAlex Vesker
4773a6c5021SAlex Vesker return arg_obj;
4783a6c5021SAlex Vesker }
4793a6c5021SAlex Vesker
mlx5dr_pat_verify_actions(__be64 pattern[],size_t sz)4803a6c5021SAlex Vesker bool mlx5dr_pat_verify_actions(__be64 pattern[], size_t sz)
4813a6c5021SAlex Vesker {
4823a6c5021SAlex Vesker size_t i;
4833a6c5021SAlex Vesker
4843a6c5021SAlex Vesker for (i = 0; i < sz / MLX5DR_MODIFY_ACTION_SIZE; i++) {
485102e59c2SErez Shitrit u8 action_id =
486102e59c2SErez Shitrit MLX5_GET(set_action_in, &pattern[i], action_type);
487102e59c2SErez Shitrit if (action_id >= MLX5_MODIFICATION_TYPE_MAX) {
4886524f0c8SAlex Vesker DR_LOG(ERR, "Invalid action %u", action_id);
489102e59c2SErez Shitrit return false;
490102e59c2SErez Shitrit }
491102e59c2SErez Shitrit }
492102e59c2SErez Shitrit
493102e59c2SErez Shitrit return true;
494102e59c2SErez Shitrit }
495