Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2014-2023 Broadcom
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include <rte_log.h>
7 : : #include <rte_malloc.h>
8 : : #include "bnxt.h"
9 : : #include "ulp_template_db_enum.h"
10 : : #include "ulp_template_struct.h"
11 : : #include "bnxt_tf_common.h"
12 : : #include "ulp_utils.h"
13 : : #include "bnxt_ulp.h"
14 : : #include "tfp.h"
15 : : #include "tf_ext_flow_handle.h"
16 : : #include "ulp_mark_mgr.h"
17 : : #include "ulp_mapper.h"
18 : : #include "ulp_flow_db.h"
19 : : #include "tf_util.h"
20 : : #include "ulp_template_db_tbl.h"
21 : : #include "ulp_port_db.h"
22 : : #include "ulp_ha_mgr.h"
23 : : #include "bnxt_tf_pmd_shim.h"
24 : :
25 : : static uint8_t mapper_fld_zeros[16] = { 0 };
26 : :
27 : : static uint8_t mapper_fld_ones[16] = {
28 : : 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
29 : : 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
30 : : };
31 : :
32 : : static uint8_t mapper_fld_one[16] = {
33 : : 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
34 : : 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
35 : : };
36 : :
37 : : static const char *
38 : : ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
39 : : {
40 : 0 : switch (tmpl_type) {
41 : : case BNXT_ULP_TEMPLATE_TYPE_CLASS:
42 : : return "class";
43 : 0 : case BNXT_ULP_TEMPLATE_TYPE_ACTION:
44 : 0 : return "action";
45 : 0 : default:
46 : 0 : return "invalid template type";
47 : : }
48 : : }
49 : :
50 : : static struct bnxt_ulp_glb_resource_info *
51 : : ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
52 : : {
53 : : if (!num_entries)
54 : : return NULL;
55 : : *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
56 : : return ulp_glb_resource_tbl;
57 : : }
58 : :
59 : : /*
60 : : * Read the global resource from the mapper global resource list
61 : : *
62 : : * The regval is always returned in big-endian.
63 : : *
64 : : * returns 0 on success
65 : : */
66 : : static int32_t
67 : : ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
68 : : enum tf_dir dir,
69 : : uint16_t idx,
70 : : uint64_t *regval,
71 : : bool *shared)
72 : : {
73 [ # # # # : 0 : if (!mapper_data || !regval || !shared ||
# # ]
74 [ # # # # : 0 : dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
# # ]
75 : : return -EINVAL;
76 : :
77 : 0 : *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
78 : 0 : *shared = mapper_data->glb_res_tbl[dir][idx].shared;
79 : : return 0;
80 : : }
81 : :
82 : : /*
83 : : * Write a global resource to the mapper global resource list
84 : : *
85 : : * The regval value must be in big-endian.
86 : : *
87 : : * return 0 on success.
88 : : */
89 : : static int32_t
90 : : ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
91 : : struct bnxt_ulp_glb_resource_info *res,
92 : : uint64_t regval, bool shared)
93 : : {
94 : : struct bnxt_ulp_mapper_glb_resource_entry *ent;
95 : :
96 : : /* validate the arguments */
97 [ # # # # : 0 : if (!data || res->direction >= TF_DIR_MAX ||
# # # # #
# # # ]
98 [ # # # # ]: 0 : res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
99 : : return -EINVAL;
100 : :
101 : : /* write to the mapper data */
102 : : ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
103 : 0 : ent->resource_func = res->resource_func;
104 : 0 : ent->resource_type = res->resource_type;
105 : 0 : ent->resource_hndl = regval;
106 : 0 : ent->shared = shared;
107 : : return 0;
108 : : }
109 : :
110 : : /*
111 : : * Internal function to allocate identity resource and store it in mapper data.
112 : : *
113 : : * returns 0 on success
114 : : */
115 : : static int32_t
116 : 0 : ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
117 : : struct bnxt_ulp_mapper_data *mapper_data,
118 : : struct bnxt_ulp_glb_resource_info *glb_res,
119 : : bool shared)
120 : : {
121 : 0 : struct tf_alloc_identifier_parms iparms = { 0 };
122 : : struct tf_free_identifier_parms fparms;
123 : : uint64_t regval;
124 : : struct tf *tfp;
125 : : int32_t rc = 0;
126 : :
127 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, shared ?
128 : : BNXT_ULP_SESSION_TYPE_SHARED :
129 : : BNXT_ULP_SESSION_TYPE_DEFAULT);
130 [ # # ]: 0 : if (!tfp)
131 : : return -EINVAL;
132 : :
133 : 0 : iparms.ident_type = glb_res->resource_type;
134 : 0 : iparms.dir = glb_res->direction;
135 : :
136 : : /* Allocate the Identifier using tf api */
137 : 0 : rc = tf_alloc_identifier(tfp, &iparms);
138 [ # # ]: 0 : if (rc) {
139 : 0 : BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
140 : : tf_dir_2_str(iparms.dir),
141 : : iparms.ident_type);
142 : 0 : return rc;
143 : : }
144 : :
145 : : /* entries are stored as big-endian format */
146 [ # # ]: 0 : regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
147 : : /*
148 : : * write to the mapper global resource
149 : : * Shared resources are never allocated through this method, so the
150 : : * shared flag is always false.
151 : : */
152 : : rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, shared);
153 : : if (rc) {
154 : 0 : BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
155 : : /* Free the identifier when update failed */
156 : 0 : fparms.dir = iparms.dir;
157 : 0 : fparms.ident_type = iparms.ident_type;
158 : 0 : fparms.id = iparms.id;
159 : 0 : tf_free_identifier(tfp, &fparms);
160 : 0 : return rc;
161 : : }
162 : : return rc;
163 : : }
164 : :
165 : : /*
166 : : * Internal function to allocate index tbl resource and store it in mapper data.
167 : : *
168 : : * returns 0 on success
169 : : */
170 : : static int32_t
171 : 0 : ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
172 : : struct bnxt_ulp_mapper_data *mapper_data,
173 : : struct bnxt_ulp_glb_resource_info *glb_res,
174 : : bool shared)
175 : : {
176 : 0 : struct tf_alloc_tbl_entry_parms aparms = { 0 };
177 : 0 : struct tf_free_tbl_entry_parms free_parms = { 0 };
178 : : uint64_t regval;
179 : : struct tf *tfp;
180 : : uint32_t tbl_scope_id;
181 : : int32_t rc = 0;
182 : :
183 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, shared ?
184 : : BNXT_ULP_SESSION_TYPE_SHARED :
185 : : BNXT_ULP_SESSION_TYPE_DEFAULT);
186 [ # # ]: 0 : if (!tfp)
187 : : return -EINVAL;
188 : :
189 : : /* Get the scope id */
190 : 0 : rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
191 [ # # ]: 0 : if (rc) {
192 : 0 : BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
193 : 0 : return rc;
194 : : }
195 : :
196 : 0 : aparms.type = glb_res->resource_type;
197 : 0 : aparms.dir = glb_res->direction;
198 : 0 : aparms.tbl_scope_id = tbl_scope_id;
199 : :
200 : : /* Allocate the index tbl using tf api */
201 : 0 : rc = tf_alloc_tbl_entry(tfp, &aparms);
202 [ # # ]: 0 : if (rc) {
203 : 0 : BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n",
204 : : tf_dir_2_str(aparms.dir), aparms.type);
205 : 0 : return rc;
206 : : }
207 : :
208 : : /* entries are stored as big-endian format */
209 [ # # ]: 0 : regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
210 : : /*
211 : : * write to the mapper global resource
212 : : * Shared resources are never allocated through this method, so the
213 : : * shared flag is always false.
214 : : */
215 : : rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, shared);
216 : : if (rc) {
217 : 0 : BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
218 : : /* Free the identifier when update failed */
219 : 0 : free_parms.dir = aparms.dir;
220 : 0 : free_parms.type = aparms.type;
221 : 0 : free_parms.idx = aparms.idx;
222 : 0 : tf_free_tbl_entry(tfp, &free_parms);
223 : 0 : return rc;
224 : : }
225 : : return rc;
226 : : }
227 : :
228 : : static int32_t
229 : 0 : ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
230 : : uint32_t operand,
231 : : uint8_t *val)
232 : : {
233 : : uint32_t t_idx;
234 : :
235 : 0 : t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT +
236 : : BNXT_ULP_HDR_SIG_ID_SHIFT +
237 : : BNXT_ULP_GLB_FIELD_TBL_SHIFT);
238 : 0 : t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
239 : : BNXT_ULP_GLB_FIELD_TBL_SHIFT);
240 [ # # ]: 0 : t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
241 : : BNXT_ULP_GLB_FIELD_TBL_SHIFT;
242 : 0 : t_idx += operand;
243 : :
244 [ # # ]: 0 : if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
245 : 0 : BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
246 : : parms->class_tid, t_idx, operand);
247 : 0 : *val = 0;
248 : 0 : return -EINVAL; /* error */
249 : : }
250 : 0 : *val = ulp_glb_field_tbl[t_idx];
251 : 0 : return 0;
252 : : }
253 : :
254 : : /*
255 : : * Get the size of the action property for a given index.
256 : : *
257 : : * idx [in] The index for the action property
258 : : *
259 : : * returns the size of the action property.
260 : : */
261 : : static uint32_t
262 : : ulp_mapper_act_prop_size_get(uint32_t idx)
263 : : {
264 : : if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
265 : : return 0;
266 : 0 : return ulp_act_prop_map_table[idx];
267 : : }
268 : :
269 : : static struct bnxt_ulp_mapper_cond_info *
270 : : ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
271 : : uint32_t tid,
272 : : uint32_t *num_tbls,
273 : : enum bnxt_ulp_cond_list_opc *opc)
274 : : {
275 : : uint32_t idx;
276 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
277 : :
278 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
279 : 0 : *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
280 : 0 : *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
281 : 0 : idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
282 : :
283 : 0 : return &dev_tbls->cond_list[idx];
284 : : }
285 : :
286 : : static struct bnxt_ulp_mapper_cond_info *
287 : : ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
288 : : struct bnxt_ulp_mapper_tbl_info *tbl,
289 : : uint32_t *num_tbls,
290 : : enum bnxt_ulp_cond_list_opc *opc)
291 : : {
292 : : uint32_t idx;
293 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
294 : :
295 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
296 : 0 : *num_tbls = tbl->execute_info.cond_nums;
297 : 0 : *opc = tbl->execute_info.cond_list_opcode;
298 : 0 : idx = tbl->execute_info.cond_start_idx;
299 : :
300 : 0 : return &dev_tbls->cond_list[idx];
301 : : }
302 : :
303 : : /*
304 : : * Get a list of classifier tables that implement the flow
305 : : * Gets a device dependent list of tables that implement the class template id
306 : : *
307 : : * mparms [in] The mappers parms with data related to the flow.
308 : : *
309 : : * tid [in] The template id that matches the flow
310 : : *
311 : : * num_tbls [out] The number of classifier tables in the returned array
312 : : *
313 : : * returns An array of classifier tables to implement the flow, or NULL on
314 : : * error
315 : : */
316 : : static struct bnxt_ulp_mapper_tbl_info *
317 : : ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
318 : : uint32_t tid,
319 : : uint32_t *num_tbls)
320 : : {
321 : : uint32_t idx;
322 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
323 : :
324 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
325 : :
326 : 0 : idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
327 : 0 : *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
328 : :
329 : 0 : return &dev_tbls->tbl_list[idx];
330 : : }
331 : :
332 : : /*
333 : : * Get the list of key fields that implement the flow.
334 : : *
335 : : * mparms [in] The mapper parms with information about the flow
336 : : *
337 : : * tbl [in] A single table instance to get the key fields from
338 : : *
339 : : * num_flds [out] The number of key fields in the returned array
340 : : *
341 : : * Returns array of Key fields, or NULL on error.
342 : : */
343 : : static struct bnxt_ulp_mapper_key_info *
344 : : ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
345 : : struct bnxt_ulp_mapper_tbl_info *tbl,
346 : : uint32_t *num_flds)
347 : : {
348 : : uint32_t idx;
349 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
350 : :
351 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
352 [ # # # # ]: 0 : if (!dev_tbls->key_info_list) {
353 : : *num_flds = 0;
354 : : return NULL;
355 : : }
356 : :
357 : 0 : idx = tbl->key_start_idx;
358 : 0 : *num_flds = tbl->key_num_fields;
359 : :
360 : 0 : return &dev_tbls->key_info_list[idx];
361 : : }
362 : :
363 : : /*
364 : : * Get the list of data fields that implement the flow.
365 : : *
366 : : * mparms [in] The mapper parms with information about the flow
367 : : *
368 : : * tbl [in] A single table instance to get the data fields from
369 : : *
370 : : * num_flds [out] The number of data fields in the returned array.
371 : : *
372 : : * num_encap_flds [out] The number of encap fields in the returned array.
373 : : *
374 : : * Returns array of data fields, or NULL on error.
375 : : */
376 : : static struct bnxt_ulp_mapper_field_info *
377 : : ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
378 : : struct bnxt_ulp_mapper_tbl_info *tbl,
379 : : uint32_t *num_flds,
380 : : uint32_t *num_encap_flds)
381 : : {
382 : : uint32_t idx;
383 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
384 : :
385 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
386 : 0 : if (!dev_tbls->result_field_list) {
387 : : *num_flds = 0;
388 : : *num_encap_flds = 0;
389 : : return NULL;
390 : : }
391 : :
392 : 0 : idx = tbl->result_start_idx;
393 : 0 : *num_flds = tbl->result_num_fields;
394 : 0 : *num_encap_flds = tbl->encap_num_fields;
395 : :
396 : 0 : return &dev_tbls->result_field_list[idx];
397 : : }
398 : :
399 : : /*
400 : : * Get the list of ident fields that implement the flow
401 : : *
402 : : * tbl [in] A single table instance to get the ident fields from
403 : : *
404 : : * num_flds [out] The number of ident fields in the returned array
405 : : *
406 : : * returns array of ident fields, or NULL on error
407 : : */
408 : : static struct bnxt_ulp_mapper_ident_info *
409 : : ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
410 : : struct bnxt_ulp_mapper_tbl_info *tbl,
411 : : uint32_t *num_flds)
412 : : {
413 : : uint32_t idx;
414 : : const struct bnxt_ulp_template_device_tbls *dev_tbls;
415 : :
416 : 0 : dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
417 [ # # ]: 0 : if (!dev_tbls->ident_list) {
418 : : *num_flds = 0;
419 : : return NULL;
420 : : }
421 : :
422 : 0 : idx = tbl->ident_start_idx;
423 : 0 : *num_flds = tbl->ident_nums;
424 : :
425 : 0 : return &dev_tbls->ident_list[idx];
426 : : }
427 : :
428 : : static enum tf_tbl_type
429 : 0 : ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms,
430 : : struct bnxt_ulp_mapper_tbl_info *tbl,
431 : : struct ulp_blob *bdata,
432 : : uint16_t *out_len)
433 : : {
434 : 0 : struct bnxt_ulp_device_params *d_params = mparms->device_params;
435 : 0 : uint16_t blob_len = ulp_blob_data_len_get(bdata);
436 : : struct bnxt_ulp_dyn_size_map *size_map;
437 : : uint32_t i;
438 : :
439 [ # # ]: 0 : if (d_params->dynamic_sram_en) {
440 [ # # # ]: 0 : switch (tbl->resource_type) {
441 : 0 : case TF_TBL_TYPE_ACT_ENCAP_8B:
442 : : case TF_TBL_TYPE_ACT_ENCAP_16B:
443 : : case TF_TBL_TYPE_ACT_ENCAP_32B:
444 : : case TF_TBL_TYPE_ACT_ENCAP_64B:
445 : : case TF_TBL_TYPE_ACT_ENCAP_128B:
446 : 0 : size_map = d_params->dyn_encap_sizes;
447 [ # # ]: 0 : for (i = 0; i < d_params->dyn_encap_list_size; i++) {
448 [ # # ]: 0 : if (blob_len <= size_map[i].slab_size) {
449 : 0 : *out_len = size_map[i].slab_size;
450 : 0 : return size_map[i].tbl_type;
451 : : }
452 : : }
453 : : break;
454 : 0 : case TF_TBL_TYPE_ACT_MODIFY_8B:
455 : : case TF_TBL_TYPE_ACT_MODIFY_16B:
456 : : case TF_TBL_TYPE_ACT_MODIFY_32B:
457 : : case TF_TBL_TYPE_ACT_MODIFY_64B:
458 : 0 : size_map = d_params->dyn_modify_sizes;
459 [ # # ]: 0 : for (i = 0; i < d_params->dyn_modify_list_size; i++) {
460 [ # # ]: 0 : if (blob_len <= size_map[i].slab_size) {
461 : 0 : *out_len = size_map[i].slab_size;
462 : 0 : return size_map[i].tbl_type;
463 : : }
464 : : }
465 : : break;
466 : : default:
467 : : break;
468 : : }
469 : : }
470 : 0 : return tbl->resource_type;
471 : : }
472 : :
473 : : static uint16_t
474 : : ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms,
475 : : struct bnxt_ulp_mapper_tbl_info *tbl)
476 : : {
477 : 0 : struct bnxt_ulp_device_params *d_params = mparms->device_params;
478 : :
479 [ # # ]: 0 : if (d_params->dynamic_sram_en) {
480 [ # # ]: 0 : switch (tbl->resource_type) {
481 : : case TF_TBL_TYPE_ACT_ENCAP_8B:
482 : : case TF_TBL_TYPE_ACT_ENCAP_16B:
483 : : case TF_TBL_TYPE_ACT_ENCAP_32B:
484 : : case TF_TBL_TYPE_ACT_ENCAP_64B:
485 : : case TF_TBL_TYPE_ACT_MODIFY_8B:
486 : : case TF_TBL_TYPE_ACT_MODIFY_16B:
487 : : case TF_TBL_TYPE_ACT_MODIFY_32B:
488 : : case TF_TBL_TYPE_ACT_MODIFY_64B:
489 : : /* return max size */
490 : : return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
491 : : default:
492 : : break;
493 : : }
494 [ # # ]: 0 : } else if (tbl->encap_num_fields) {
495 : : return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
496 : : }
497 : 0 : return tbl->result_bit_size;
498 : : }
499 : :
500 : : static inline int32_t
501 : 0 : ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp,
502 : : struct tf *tfp,
503 : : struct ulp_flow_db_res_params *res)
504 : : {
505 : 0 : struct tf_free_tcam_entry_parms fparms = {
506 : 0 : .dir = res->direction,
507 : 0 : .tcam_tbl_type = res->resource_type,
508 : 0 : .idx = (uint16_t)res->resource_hndl
509 : : };
510 : :
511 : : /* If HA is enabled, we may have to remap the TF Type */
512 [ # # ]: 0 : if (bnxt_ulp_cntxt_ha_enabled(ulp)) {
513 : : enum ulp_ha_mgr_region region;
514 : : int32_t rc;
515 : :
516 [ # # ]: 0 : switch (res->resource_type) {
517 : 0 : case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH:
518 : : case TF_TCAM_TBL_TYPE_WC_TCAM_LOW:
519 : 0 : rc = ulp_ha_mgr_region_get(ulp, ®ion);
520 [ # # ]: 0 : if (rc)
521 : : /* Log this, but assume region is correct */
522 : 0 : BNXT_TF_DBG(ERR,
523 : : "Unable to get HA region (%d)\n",
524 : : rc);
525 : : else
526 : 0 : fparms.tcam_tbl_type =
527 : 0 : (region == ULP_HA_REGION_LOW) ?
528 [ # # ]: 0 : TF_TCAM_TBL_TYPE_WC_TCAM_LOW :
529 : : TF_TCAM_TBL_TYPE_WC_TCAM_HIGH;
530 : : break;
531 : : default:
532 : : break;
533 : : }
534 : : }
535 : 0 : return tf_free_tcam_entry(tfp, &fparms);
536 : : }
537 : :
538 : : static int32_t
539 : 0 : ulp_mapper_clear_full_action_record(struct tf *tfp,
540 : : struct bnxt_ulp_context *ulp_ctx,
541 : : struct tf_free_tbl_entry_parms *fparms)
542 : : {
543 : 0 : struct tf_set_tbl_entry_parms sparms = { 0 };
544 : 0 : uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST;
545 : : int32_t rc = 0;
546 : :
547 : 0 : rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
548 [ # # ]: 0 : if (rc) {
549 : 0 : BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
550 : 0 : return rc;
551 : : }
552 : :
553 [ # # ]: 0 : if (dev_id == BNXT_ULP_DEVICE_ID_THOR) {
554 : 0 : sparms.dir = fparms->dir;
555 : 0 : sparms.data = mapper_fld_zeros;
556 : 0 : sparms.type = fparms->type;
557 : 0 : sparms.data_sz_in_bytes = 16; /* FULL ACT REC SIZE - THOR */
558 : 0 : sparms.idx = fparms->idx;
559 : 0 : sparms.tbl_scope_id = fparms->tbl_scope_id;
560 : 0 : rc = tf_set_tbl_entry(tfp, &sparms);
561 [ # # ]: 0 : if (rc) {
562 : 0 : BNXT_TF_DBG(ERR,
563 : : "Index table[%s][%s][%x] write fail rc=%d\n",
564 : : tf_tbl_type_2_str(sparms.type),
565 : : tf_dir_2_str(sparms.dir),
566 : : sparms.idx, rc);
567 : 0 : return rc;
568 : : }
569 : : }
570 : : return 0;
571 : : }
572 : :
573 : : static inline int32_t
574 : 0 : ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
575 : : struct tf *tfp,
576 : : struct ulp_flow_db_res_params *res)
577 : : {
578 : 0 : struct tf_free_tbl_entry_parms fparms = {
579 : 0 : .dir = res->direction,
580 : 0 : .type = res->resource_type,
581 : 0 : .idx = (uint32_t)res->resource_hndl
582 : : };
583 : :
584 : : /*
585 : : * Just get the table scope, it will be ignored if not necessary
586 : : * by the tf_free_tbl_entry
587 : : */
588 : 0 : (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
589 : :
590 [ # # ]: 0 : if (fparms.type == TF_TBL_TYPE_FULL_ACT_RECORD)
591 : 0 : (void)ulp_mapper_clear_full_action_record(tfp, ulp, &fparms);
592 : :
593 : 0 : return tf_free_tbl_entry(tfp, &fparms);
594 : : }
595 : :
596 : : static inline int32_t
597 : 0 : ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
598 : : struct tf *tfp,
599 : : struct ulp_flow_db_res_params *res)
600 : : {
601 : 0 : struct tf_delete_em_entry_parms fparms = { 0 };
602 : : int32_t rc;
603 : :
604 : 0 : fparms.dir = res->direction;
605 : 0 : fparms.flow_handle = res->resource_hndl;
606 : :
607 : 0 : rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
608 [ # # ]: 0 : if (rc) {
609 : 0 : BNXT_TF_DBG(ERR, "Failed to get table scope\n");
610 : 0 : return -EINVAL;
611 : : }
612 : :
613 : 0 : return tf_delete_em_entry(tfp, &fparms);
614 : : }
615 : :
616 : : static inline int32_t
617 : : ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
618 : : struct tf *tfp,
619 : : struct ulp_flow_db_res_params *res)
620 : : {
621 : 0 : struct tf_free_identifier_parms fparms = {
622 : 0 : .dir = res->direction,
623 : 0 : .ident_type = res->resource_type,
624 : 0 : .id = (uint16_t)res->resource_hndl
625 : : };
626 : :
627 : 0 : return tf_free_identifier(tfp, &fparms);
628 : : }
629 : :
630 : : static inline int32_t
631 : : ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
632 : : struct ulp_flow_db_res_params *res)
633 : : {
634 : 0 : return ulp_mark_db_mark_del(ulp,
635 : 0 : res->resource_type,
636 : 0 : res->resource_hndl);
637 : : }
638 : :
639 : : static inline int32_t
640 : 0 : ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
641 : : uint32_t parent_fid,
642 : : struct ulp_flow_db_res_params *res)
643 : : {
644 : : uint32_t pc_idx;
645 : :
646 : 0 : pc_idx = (uint32_t)res->resource_hndl;
647 : :
648 : : /* reset the child flow bitset*/
649 [ # # ]: 0 : if (ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0)) {
650 : 0 : BNXT_TF_DBG(ERR, "error in reset parent flow bitset %x:%x\n",
651 : : pc_idx, parent_fid);
652 : 0 : return -EINVAL;
653 : : }
654 : : return 0;
655 : : }
656 : :
657 : : static inline int32_t
658 : 0 : ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
659 : : uint32_t child_fid,
660 : : struct ulp_flow_db_res_params *res)
661 : : {
662 : : uint32_t pc_idx;
663 : :
664 : 0 : pc_idx = (uint32_t)res->resource_hndl;
665 : :
666 : : /* reset the child flow bitset*/
667 [ # # ]: 0 : if (ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0)) {
668 : 0 : BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
669 : : pc_idx, child_fid);
670 : 0 : return -EINVAL;
671 : : }
672 : : return 0;
673 : : }
674 : :
675 : : /*
676 : : * Process the flow database opcode alloc action.
677 : : * returns 0 on success
678 : : */
679 : : static int32_t
680 : 0 : ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
681 : : struct bnxt_ulp_mapper_tbl_info *tbl)
682 : : {
683 : 0 : uint32_t rid = 0;
684 : : uint64_t val64;
685 : : int32_t rc = 0;
686 : :
687 : : /* allocate a new fid */
688 : 0 : rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
689 : : BNXT_ULP_FDB_TYPE_RID,
690 : : 0, &rid);
691 [ # # ]: 0 : if (rc) {
692 : 0 : BNXT_TF_DBG(ERR,
693 : : "Unable to allocate flow table entry\n");
694 : 0 : return -EINVAL;
695 : : }
696 : : /* Store the allocated fid in regfile*/
697 : 0 : val64 = rid;
698 : 0 : rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
699 [ # # ]: 0 : tfp_cpu_to_be_64(val64));
700 [ # # ]: 0 : if (rc) {
701 : 0 : BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
702 : : tbl->fdb_operand);
703 : 0 : ulp_flow_db_fid_free(parms->ulp_ctx,
704 : : BNXT_ULP_FDB_TYPE_RID, rid);
705 : 0 : return -EINVAL;
706 : : }
707 : : /* save the rid into the parms in case a flow fails before pushing the
708 : : * rid into the fid
709 : : */
710 : 0 : parms->rid = rid;
711 : 0 : return 0;
712 : : }
713 : :
714 : : /*
715 : : * Process the flow database opcode action.
716 : : * returns 0 on success.
717 : : */
718 : : static int32_t
719 : 0 : ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
720 : : struct bnxt_ulp_mapper_tbl_info *tbl,
721 : : struct ulp_flow_db_res_params *fid_parms)
722 : : {
723 : : uint32_t push_fid;
724 : : uint64_t val64;
725 : : enum bnxt_ulp_fdb_type flow_type;
726 : : int32_t rc = 0;
727 : :
728 [ # # # ]: 0 : switch (tbl->fdb_opcode) {
729 : 0 : case BNXT_ULP_FDB_OPC_PUSH_FID:
730 : 0 : push_fid = parms->fid;
731 : 0 : flow_type = parms->flow_type;
732 : 0 : break;
733 : 0 : case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
734 : : /* get the fid from the regfile */
735 : 0 : rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
736 : : &val64);
737 [ # # ]: 0 : if (!rc) {
738 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
739 : : tbl->fdb_operand);
740 : 0 : return -EINVAL;
741 : : }
742 : : /* Use the extracted fid to update the flow resource */
743 [ # # ]: 0 : push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
744 : : flow_type = BNXT_ULP_FDB_TYPE_RID;
745 : : break;
746 : : default:
747 : : return rc; /* Nothing to be done */
748 : : }
749 : :
750 : : /* Add the resource to the flow database */
751 : 0 : rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
752 : : push_fid, fid_parms);
753 [ # # ]: 0 : if (rc)
754 : 0 : BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
755 : : push_fid, rc);
756 : : return rc;
757 : : }
758 : :
759 : : /*
760 : : * Process the flow database opcode action.
761 : : * returns 0 on success.
762 : : */
763 : : static int32_t
764 : 0 : ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
765 : : struct bnxt_ulp_mapper_tbl_info *tbl,
766 : : uint32_t *priority)
767 : : {
768 : : int32_t rc = 0;
769 : :
770 [ # # # # : 0 : switch (tbl->pri_opcode) {
# ]
771 : 0 : case BNXT_ULP_PRI_OPC_NOT_USED:
772 : 0 : *priority = 0;
773 : 0 : break;
774 : 0 : case BNXT_ULP_PRI_OPC_CONST:
775 : 0 : *priority = tbl->pri_operand;
776 : 0 : break;
777 : 0 : case BNXT_ULP_PRI_OPC_APP_PRI:
778 : 0 : *priority = parms->app_priority;
779 : 0 : break;
780 : 0 : case BNXT_ULP_PRI_OPC_APP_PRI_OR_CONST:
781 [ # # ]: 0 : if (parms->app_priority)
782 : 0 : *priority = parms->app_priority;
783 : : else
784 : 0 : *priority = tbl->pri_operand;
785 : : break;
786 : 0 : default:
787 : 0 : BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
788 : : tbl->pri_opcode);
789 : : rc = -EINVAL;
790 : 0 : break;
791 : : }
792 : 0 : return rc;
793 : : }
794 : :
795 : : /*
796 : : * Process the identifier list in the given table.
797 : : * Extract the ident from the table entry and
798 : : * write it to the reg file.
799 : : * returns 0 on success.
800 : : */
801 : : static int32_t
802 : 0 : ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
803 : : struct bnxt_ulp_mapper_tbl_info *tbl,
804 : : uint8_t *byte_data,
805 : : uint32_t byte_data_size,
806 : : enum bnxt_ulp_byte_order byte_order)
807 : : {
808 : : struct bnxt_ulp_mapper_ident_info *idents;
809 : : uint32_t i, num_idents = 0;
810 : : uint64_t val64;
811 : :
812 : : /* validate the null arguments */
813 [ # # ]: 0 : if (!byte_data) {
814 : 0 : BNXT_TF_DBG(ERR, "invalid argument\n");
815 : 0 : return -EINVAL;
816 : : }
817 : :
818 : : /* Get the ident list and process each one */
819 : : idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
820 : :
821 [ # # ]: 0 : for (i = 0; i < num_idents; i++) {
822 : : /* check the size of the buffer for validation */
823 : 0 : if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
824 [ # # # # ]: 0 : ULP_BYTE_2_BITS(byte_data_size) ||
825 : : idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
826 : 0 : BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
827 : : idents[i].ident_bit_pos,
828 : : idents[i].ident_bit_size,
829 : : byte_data_size);
830 : 0 : return -EINVAL;
831 : : }
832 : 0 : val64 = 0;
833 [ # # ]: 0 : if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
834 : 0 : ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
835 : : sizeof(val64),
836 : : idents[i].ident_bit_pos,
837 : : idents[i].ident_bit_size);
838 : : else
839 : 0 : ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
840 : : idents[i].ident_bit_pos,
841 : : idents[i].ident_bit_size);
842 : :
843 : : /* Write it to the regfile, val64 is already in big-endian*/
844 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile,
845 : : idents[i].regfile_idx, val64)) {
846 : 0 : BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
847 : : idents[i].regfile_idx);
848 : 0 : return -EINVAL;
849 : : }
850 : : }
851 : : return 0;
852 : : }
853 : :
854 : : /*
855 : : * Process the identifier instruction and either store it in the flow database
856 : : * or return it in the val (if not NULL) on success. If val is NULL, the
857 : : * identifier is to be stored in the flow database.
858 : : */
859 : : static int32_t
860 : 0 : ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
861 : : struct bnxt_ulp_mapper_tbl_info *tbl,
862 : : struct bnxt_ulp_mapper_ident_info *ident,
863 : : uint16_t *val)
864 : : {
865 : : struct ulp_flow_db_res_params fid_parms;
866 : : uint64_t id = 0;
867 : : int32_t idx;
868 : 0 : struct tf_alloc_identifier_parms iparms = { 0 };
869 : 0 : struct tf_free_identifier_parms free_parms = { 0 };
870 : : struct tf *tfp;
871 : : int rc;
872 : :
873 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
874 [ # # ]: 0 : if (!tfp) {
875 : 0 : BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
876 : 0 : return -EINVAL;
877 : : }
878 : :
879 : 0 : idx = ident->regfile_idx;
880 : :
881 : 0 : iparms.ident_type = ident->ident_type;
882 : 0 : iparms.dir = tbl->direction;
883 : :
884 : 0 : rc = tf_alloc_identifier(tfp, &iparms);
885 [ # # ]: 0 : if (rc) {
886 : 0 : BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
887 : : tf_dir_2_str(iparms.dir),
888 : : tf_ident_2_str(iparms.ident_type));
889 : 0 : return rc;
890 : : }
891 : 0 : BNXT_TF_DBG(DEBUG, "Alloc ident %s:%s.success.\n",
892 : : tf_dir_2_str(iparms.dir),
893 : : tf_ident_2_str(iparms.ident_type));
894 : :
895 [ # # ]: 0 : id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
896 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile, idx, id)) {
897 : 0 : BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
898 : : rc = -EINVAL;
899 : : /* Need to free the identifier, so goto error */
900 : 0 : goto error;
901 : : }
902 : :
903 : : /* Link the resource to the flow in the flow db */
904 [ # # ]: 0 : if (!val) {
905 : : memset(&fid_parms, 0, sizeof(fid_parms));
906 : 0 : fid_parms.direction = tbl->direction;
907 : 0 : fid_parms.resource_func = ident->resource_func;
908 : 0 : fid_parms.resource_type = ident->ident_type;
909 : 0 : fid_parms.resource_hndl = iparms.id;
910 : 0 : fid_parms.critical_resource = tbl->critical_resource;
911 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
912 : :
913 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
914 [ # # ]: 0 : if (rc) {
915 : 0 : BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
916 : : rc);
917 : : /* Need to free the identifier, so goto error */
918 : 0 : goto error;
919 : : }
920 : : } else {
921 : 0 : *val = iparms.id;
922 : : }
923 : : return 0;
924 : :
925 : 0 : error:
926 : : /* Need to free the identifier */
927 : 0 : free_parms.dir = tbl->direction;
928 : 0 : free_parms.ident_type = ident->ident_type;
929 : 0 : free_parms.id = iparms.id;
930 : :
931 : 0 : (void)tf_free_identifier(tfp, &free_parms);
932 : :
933 : 0 : BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
934 : : ident->description,
935 : : tf_dir_2_str(tbl->direction));
936 : 0 : return rc;
937 : : }
938 : :
939 : : /*
940 : : * Process the identifier instruction and extract it from result blob.
941 : : * Increment the identifier reference count and store it in the flow database.
942 : : */
943 : : static int32_t
944 : 0 : ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
945 : : struct bnxt_ulp_mapper_tbl_info *tbl,
946 : : struct bnxt_ulp_mapper_ident_info *ident,
947 : : struct ulp_blob *res_blob)
948 : : {
949 : : struct ulp_flow_db_res_params fid_parms;
950 : : uint64_t id = 0;
951 : 0 : uint32_t idx = 0;
952 : 0 : struct tf_search_identifier_parms sparms = { 0 };
953 : 0 : struct tf_free_identifier_parms free_parms = { 0 };
954 : : struct tf *tfp;
955 : : int rc;
956 : :
957 : : /* Get the tfp from ulp context */
958 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
959 [ # # ]: 0 : if (!tfp) {
960 : 0 : BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
961 : 0 : return -EINVAL;
962 : : }
963 : :
964 : : /* Extract the index from the result blob */
965 : 0 : rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
966 : 0 : ident->ident_bit_pos, ident->ident_bit_size);
967 [ # # ]: 0 : if (rc) {
968 : 0 : BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
969 : 0 : return -EIO;
970 : : }
971 : :
972 : : /* populate the search params and search identifier shadow table */
973 : 0 : sparms.ident_type = ident->ident_type;
974 : 0 : sparms.dir = tbl->direction;
975 : : /* convert the idx into cpu format */
976 [ # # ]: 0 : sparms.search_id = tfp_be_to_cpu_32(idx);
977 : :
978 : : /* Search identifier also increase the reference count */
979 : 0 : rc = tf_search_identifier(tfp, &sparms);
980 [ # # ]: 0 : if (rc) {
981 : 0 : BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
982 : : tf_dir_2_str(sparms.dir),
983 : : tf_ident_2_str(sparms.ident_type),
984 : : sparms.search_id);
985 : 0 : return rc;
986 : : }
987 : 0 : BNXT_TF_DBG(DEBUG, "Search ident %s:%s:%x.success.\n",
988 : : tf_dir_2_str(sparms.dir),
989 : : tf_ident_2_str(sparms.ident_type),
990 : : sparms.search_id);
991 : :
992 : : /* Write it to the regfile */
993 [ # # ]: 0 : id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
994 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
995 : 0 : BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
996 : : rc = -EINVAL;
997 : : /* Need to free the identifier, so goto error */
998 : 0 : goto error;
999 : : }
1000 : :
1001 : : /* Link the resource to the flow in the flow db */
1002 : : memset(&fid_parms, 0, sizeof(fid_parms));
1003 : 0 : fid_parms.direction = tbl->direction;
1004 : 0 : fid_parms.resource_func = ident->resource_func;
1005 : 0 : fid_parms.resource_type = ident->ident_type;
1006 : 0 : fid_parms.resource_hndl = sparms.search_id;
1007 : 0 : fid_parms.critical_resource = tbl->critical_resource;
1008 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1009 : :
1010 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1011 [ # # ]: 0 : if (rc) {
1012 : 0 : BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
1013 : : rc);
1014 : : /* Need to free the identifier, so goto error */
1015 : 0 : goto error;
1016 : : }
1017 : :
1018 : : return 0;
1019 : :
1020 : 0 : error:
1021 : : /* Need to free the identifier */
1022 : 0 : free_parms.dir = tbl->direction;
1023 : 0 : free_parms.ident_type = ident->ident_type;
1024 : 0 : free_parms.id = sparms.search_id;
1025 : 0 : (void)tf_free_identifier(tfp, &free_parms);
1026 : 0 : BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
1027 : : ident->description,
1028 : : tf_dir_2_str(tbl->direction), sparms.search_id);
1029 : 0 : return rc;
1030 : : }
1031 : :
1032 : : static int32_t
1033 : 0 : ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
1034 : : uint32_t port_id,
1035 : : uint16_t val16,
1036 : : uint8_t **val)
1037 : : {
1038 : 0 : enum bnxt_ulp_port_table port_data = val16;
1039 : :
1040 [ # # # # : 0 : switch (port_data) {
# # ]
1041 : 0 : case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
1042 [ # # ]: 0 : if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
1043 : : val)) {
1044 : 0 : BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1045 : 0 : return -EINVAL;
1046 : : }
1047 : : break;
1048 : 0 : case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
1049 [ # # ]: 0 : if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
1050 : : val)) {
1051 : 0 : BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1052 : 0 : return -EINVAL;
1053 : : }
1054 : : break;
1055 : 0 : case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
1056 [ # # ]: 0 : if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
1057 : : val)) {
1058 : 0 : BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1059 : 0 : return -EINVAL;
1060 : : }
1061 : : break;
1062 : 0 : case BNXT_ULP_PORT_TABLE_PORT_IS_PF:
1063 [ # # ]: 0 : if (ulp_port_db_port_is_pf_get(parms->ulp_ctx, port_id,
1064 : : val)) {
1065 : 0 : BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1066 : 0 : return -EINVAL;
1067 : : }
1068 : : break;
1069 : 0 : case BNXT_ULP_PORT_TABLE_VF_FUNC_METADATA:
1070 [ # # ]: 0 : if (ulp_port_db_port_meta_data_get(parms->ulp_ctx, port_id,
1071 : : val)) {
1072 : 0 : BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1073 : 0 : return -EINVAL;
1074 : : }
1075 : : break;
1076 : 0 : default:
1077 : 0 : BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
1078 : 0 : return -EINVAL;
1079 : : }
1080 : : return 0;
1081 : : }
1082 : :
1083 : : static int32_t
1084 : 0 : ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
1085 : : enum bnxt_ulp_field_src field_src,
1086 : : uint8_t *field_opr,
1087 : : enum tf_dir dir,
1088 : : uint8_t is_key,
1089 : : uint32_t bitlen,
1090 : : uint8_t **val,
1091 : : uint32_t *val_len,
1092 : : uint64_t *value)
1093 : : {
1094 : : struct bnxt_ulp_mapper_data *m;
1095 : : uint8_t bit;
1096 : : uint32_t port_id, val_size, field_size;
1097 : : uint16_t idx, size_idx, offset;
1098 : 0 : uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
1099 : : uint8_t *buffer;
1100 : : uint64_t lregval;
1101 : : bool shared;
1102 : : uint8_t i = 0;
1103 : :
1104 : 0 : *val_len = bitlen;
1105 : 0 : *value = 0;
1106 : : /* Perform the action */
1107 [ # # # # : 0 : switch (field_src) {
# # # # #
# # # # #
# # # # ]
1108 : 0 : case BNXT_ULP_FIELD_SRC_ZERO:
1109 : 0 : *val = mapper_fld_zeros;
1110 : 0 : break;
1111 : 0 : case BNXT_ULP_FIELD_SRC_CONST:
1112 : 0 : *val = field_opr;
1113 : 0 : break;
1114 : 0 : case BNXT_ULP_FIELD_SRC_ONES:
1115 : 0 : *val = mapper_fld_ones;
1116 : 0 : *value = 1;
1117 : 0 : break;
1118 : 0 : case BNXT_ULP_FIELD_SRC_CF:
1119 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1120 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1121 : 0 : BNXT_TF_DBG(ERR, "CF operand read failed\n");
1122 : 0 : return -EINVAL;
1123 : : }
1124 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1125 [ # # # # ]: 0 : if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
1126 : 0 : BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1127 : : bytelen);
1128 : 0 : return -EINVAL;
1129 : : }
1130 : 0 : buffer = (uint8_t *)&parms->comp_fld[idx];
1131 : 0 : *val = &buffer[sizeof(uint64_t) - bytelen];
1132 [ # # ]: 0 : *value = ULP_COMP_FLD_IDX_RD(parms, idx);
1133 : 0 : break;
1134 : 0 : case BNXT_ULP_FIELD_SRC_RF:
1135 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1136 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1137 : 0 : BNXT_TF_DBG(ERR, "RF operand read failed\n");
1138 : 0 : return -EINVAL;
1139 : : }
1140 : :
1141 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1142 : : /* Uninitialized regfile entries return 0 */
1143 [ # # # # ]: 0 : if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
1144 : : sizeof(uint64_t) < bytelen) {
1145 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
1146 : : bytelen);
1147 : 0 : return -EINVAL;
1148 : : }
1149 : 0 : buffer = (uint8_t *)&parms->regfile->entry[idx].data;
1150 : 0 : *val = &buffer[sizeof(uint64_t) - bytelen];
1151 [ # # ]: 0 : *value = tfp_be_to_cpu_64(lregval);
1152 : 0 : break;
1153 : 0 : case BNXT_ULP_FIELD_SRC_ACT_PROP:
1154 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1155 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1156 : 0 : BNXT_TF_DBG(ERR, "Action operand read failed\n");
1157 : 0 : return -EINVAL;
1158 : : }
1159 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1160 [ # # ]: 0 : if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1161 : 0 : BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
1162 : 0 : return -EINVAL;
1163 : : }
1164 : 0 : buffer = &parms->act_prop->act_details[idx];
1165 : 0 : field_size = ulp_mapper_act_prop_size_get(idx);
1166 [ # # ]: 0 : if (bytelen > field_size) {
1167 : 0 : BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
1168 : : idx, field_size);
1169 : 0 : return -EINVAL;
1170 : : }
1171 : 0 : *val = &buffer[field_size - bytelen];
1172 [ # # ]: 0 : if (sizeof(*value) >= field_size) {
1173 : 0 : *value = buffer[0];
1174 [ # # ]: 0 : for (i = 1; i < field_size; i++)
1175 : 0 : *value = (*value << 8) | buffer[i];
1176 : : }
1177 : : break;
1178 : 0 : case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1179 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1180 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1181 : 0 : BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1182 : 0 : return -EINVAL;
1183 : : }
1184 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1185 : :
1186 [ # # ]: 0 : if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1187 : 0 : BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
1188 : 0 : return -EINVAL;
1189 : : }
1190 : 0 : *val = &parms->act_prop->act_details[idx];
1191 : :
1192 : : /* get the size index next */
1193 [ # # ]: 0 : if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1194 : : (uint8_t *)&size_idx, sizeof(uint16_t))) {
1195 : 0 : BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1196 : 0 : return -EINVAL;
1197 : : }
1198 [ # # ]: 0 : size_idx = tfp_be_to_cpu_16(size_idx);
1199 [ # # ]: 0 : if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1200 : 0 : BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1201 : 0 : return -EINVAL;
1202 : : }
1203 : 0 : memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1204 : : sizeof(uint32_t));
1205 [ # # ]: 0 : val_size = tfp_be_to_cpu_32(val_size);
1206 : 0 : *val_len = ULP_BYTE_2_BITS(val_size);
1207 : 0 : break;
1208 : 0 : case BNXT_ULP_FIELD_SRC_GLB_RF:
1209 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1210 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1211 : 0 : BNXT_TF_DBG(ERR, "Global regfile read failed\n");
1212 : 0 : return -EINVAL;
1213 : : }
1214 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1215 [ # # ]: 0 : if (ulp_mapper_glb_resource_read(parms->mapper_data,
1216 [ # # ]: 0 : dir, idx, &lregval, &shared) ||
1217 : : sizeof(uint64_t) < bytelen) {
1218 : 0 : BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
1219 : : idx, bytelen);
1220 : 0 : return -EINVAL;
1221 : : }
1222 : : m = parms->mapper_data;
1223 : 0 : buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
1224 : 0 : *val = &buffer[sizeof(uint64_t) - bytelen];
1225 [ # # ]: 0 : *value = tfp_be_to_cpu_64(lregval);
1226 : 0 : break;
1227 : 0 : case BNXT_ULP_FIELD_SRC_HF:
1228 : : case BNXT_ULP_FIELD_SRC_SUB_HF:
1229 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1230 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1231 : 0 : BNXT_TF_DBG(ERR, "Header field read failed\n");
1232 : 0 : return -EINVAL;
1233 : : }
1234 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1235 : : /* get the index from the global field list */
1236 [ # # ]: 0 : if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1237 : 0 : BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1238 : : idx);
1239 : 0 : return -EINVAL;
1240 : : }
1241 [ # # ]: 0 : if (is_key)
1242 : 0 : buffer = parms->hdr_field[bit].spec;
1243 : : else
1244 : 0 : buffer = parms->hdr_field[bit].mask;
1245 : :
1246 : 0 : field_size = parms->hdr_field[bit].size;
1247 [ # # ]: 0 : if (bytelen > field_size) {
1248 : 0 : BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
1249 : : bit, field_size);
1250 : 0 : return -EINVAL;
1251 : : }
1252 [ # # ]: 0 : if (field_src == BNXT_ULP_FIELD_SRC_HF) {
1253 : 0 : *val = &buffer[field_size - bytelen];
1254 : : } else {
1255 : : /* get the offset next */
1256 [ # # ]: 0 : if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1257 : : (uint8_t *)&offset,
1258 : : sizeof(uint16_t))) {
1259 : 0 : BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
1260 : 0 : return -EINVAL;
1261 : : }
1262 [ # # ]: 0 : offset = tfp_be_to_cpu_16(offset);
1263 : 0 : offset = ULP_BITS_2_BYTE_NR(offset);
1264 [ # # ]: 0 : if ((offset + bytelen) > field_size) {
1265 : 0 : BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
1266 : 0 : return -EINVAL;
1267 : : }
1268 : 0 : *val = &buffer[offset];
1269 : : }
1270 : : break;
1271 : 0 : case BNXT_ULP_FIELD_SRC_HDR_BIT:
1272 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1273 : : (uint8_t *)&lregval, sizeof(uint64_t))) {
1274 : 0 : BNXT_TF_DBG(ERR, "Header bit read failed\n");
1275 : 0 : return -EINVAL;
1276 : : }
1277 [ # # ]: 0 : lregval = tfp_be_to_cpu_64(lregval);
1278 [ # # ]: 0 : if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
1279 : 0 : *val = mapper_fld_one;
1280 : 0 : *value = 1;
1281 : : } else {
1282 : 0 : *val = mapper_fld_zeros;
1283 : : }
1284 : : break;
1285 : 0 : case BNXT_ULP_FIELD_SRC_ACT_BIT:
1286 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1287 : : (uint8_t *)&lregval, sizeof(uint64_t))) {
1288 : 0 : BNXT_TF_DBG(ERR, "Action bit read failed\n");
1289 : 0 : return -EINVAL;
1290 : : }
1291 [ # # ]: 0 : lregval = tfp_be_to_cpu_64(lregval);
1292 [ # # ]: 0 : if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
1293 : 0 : *val = mapper_fld_one;
1294 : 0 : *value = 1;
1295 : : } else {
1296 : 0 : *val = mapper_fld_zeros;
1297 : : }
1298 : : break;
1299 : 0 : case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1300 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1301 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1302 : 0 : BNXT_TF_DBG(ERR, "Field bit read failed\n");
1303 : 0 : return -EINVAL;
1304 : : }
1305 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1306 : : /* get the index from the global field list */
1307 [ # # ]: 0 : if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1308 : 0 : BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1309 : : idx);
1310 : 0 : return -EINVAL;
1311 : : }
1312 [ # # ]: 0 : if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
1313 : 0 : *val = mapper_fld_one;
1314 : 0 : *value = 1;
1315 : : } else {
1316 : 0 : *val = mapper_fld_zeros;
1317 : : }
1318 : : break;
1319 : 0 : case BNXT_ULP_FIELD_SRC_PORT_TABLE:
1320 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1321 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1322 : 0 : BNXT_TF_DBG(ERR, "CF operand read failed\n");
1323 : 0 : return -EINVAL;
1324 : : }
1325 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1326 [ # # # # ]: 0 : if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
1327 : 0 : BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1328 : : bytelen);
1329 : 0 : return -EINVAL;
1330 : : }
1331 : :
1332 : : /* The port id is present in the comp field list */
1333 [ # # ]: 0 : port_id = ULP_COMP_FLD_IDX_RD(parms, idx);
1334 : : /* get the port table enum */
1335 [ # # ]: 0 : if (!ulp_operand_read(field_opr + sizeof(uint16_t),
1336 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1337 : 0 : BNXT_TF_DBG(ERR, "Port table enum read failed\n");
1338 : 0 : return -EINVAL;
1339 : : }
1340 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1341 [ # # ]: 0 : if (ulp_mapper_field_port_db_process(parms, port_id, idx,
1342 : : val)) {
1343 : 0 : BNXT_TF_DBG(ERR, "field port table failed\n");
1344 : 0 : return -EINVAL;
1345 : : }
1346 : : break;
1347 : 0 : case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT:
1348 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1349 : : (uint8_t *)&lregval, sizeof(uint64_t))) {
1350 : 0 : BNXT_TF_DBG(ERR, "Header bit read failed\n");
1351 : 0 : return -EINVAL;
1352 : : }
1353 [ # # ]: 0 : lregval = tfp_be_to_cpu_64(lregval);
1354 [ # # ]: 0 : if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) {
1355 : 0 : *val = mapper_fld_one;
1356 : 0 : *value = 1;
1357 : : } else {
1358 : 0 : *val = mapper_fld_zeros;
1359 : : }
1360 : : break;
1361 : 0 : case BNXT_ULP_FIELD_SRC_ENC_FIELD:
1362 [ # # ]: 0 : if (!ulp_operand_read(field_opr,
1363 : : (uint8_t *)&idx, sizeof(uint16_t))) {
1364 : 0 : BNXT_TF_DBG(ERR, "Header field read failed\n");
1365 : 0 : return -EINVAL;
1366 : : }
1367 [ # # ]: 0 : idx = tfp_be_to_cpu_16(idx);
1368 : : /* get the index from the global field list */
1369 [ # # ]: 0 : if (idx >= BNXT_ULP_ENC_FIELD_LAST) {
1370 : 0 : BNXT_TF_DBG(ERR, "invalid encap field tbl idx %d\n",
1371 : : idx);
1372 : 0 : return -EINVAL;
1373 : : }
1374 : 0 : buffer = parms->enc_field[idx].spec;
1375 : 0 : field_size = parms->enc_field[idx].size;
1376 [ # # ]: 0 : if (bytelen > field_size) {
1377 : 0 : BNXT_TF_DBG(ERR, "Encap field[%d] size small %u\n",
1378 : : idx, field_size);
1379 : 0 : return -EINVAL;
1380 : : }
1381 : 0 : *val = &buffer[field_size - bytelen];
1382 : 0 : break;
1383 : 0 : case BNXT_ULP_FIELD_SRC_SKIP:
1384 : : /* do nothing */
1385 : 0 : *val = mapper_fld_zeros;
1386 : 0 : *val_len = 0;
1387 : 0 : break;
1388 : : case BNXT_ULP_FIELD_SRC_REJECT:
1389 : : return -EINVAL;
1390 : 0 : default:
1391 : 0 : BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
1392 : 0 : return -EINVAL;
1393 : : }
1394 : : return 0;
1395 : : }
1396 : :
1397 : 0 : static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
1398 : : uint64_t *output)
1399 : : {
1400 : : uint16_t val_16;
1401 : : uint32_t val_32;
1402 : : uint64_t val_64;
1403 : : uint32_t bytelen;
1404 : :
1405 : 0 : bytelen = ULP_BITS_2_BYTE(bitlen);
1406 [ # # ]: 0 : if (bytelen == sizeof(uint8_t)) {
1407 : 0 : *output = *((uint8_t *)buffer);
1408 [ # # ]: 0 : } else if (bytelen == sizeof(uint16_t)) {
1409 : 0 : val_16 = *((uint16_t *)buffer);
1410 [ # # ]: 0 : *output = tfp_be_to_cpu_16(val_16);
1411 [ # # ]: 0 : } else if (bytelen == sizeof(uint32_t)) {
1412 : 0 : val_32 = *((uint32_t *)buffer);
1413 [ # # ]: 0 : *output = tfp_be_to_cpu_32(val_32);
1414 [ # # ]: 0 : } else if (bytelen == sizeof(val_64)) {
1415 : 0 : val_64 = *((uint64_t *)buffer);
1416 [ # # ]: 0 : *output = tfp_be_to_cpu_64(val_64);
1417 : : } else {
1418 : 0 : *output = 0;
1419 : 0 : return -EINVAL;
1420 : : }
1421 : : return 0;
1422 : : }
1423 : :
1424 : 0 : static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
1425 : : struct ulp_blob *blob,
1426 : : uint8_t *val,
1427 : : uint32_t val_len,
1428 : : uint8_t **out_val)
1429 : : {
1430 [ # # ]: 0 : if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
1431 [ # # ]: 0 : if (ulp_blob_pad_push(blob, val_len) < 0) {
1432 : 0 : BNXT_TF_DBG(ERR, "too large for blob\n");
1433 : 0 : return -EINVAL;
1434 : : }
1435 [ # # ]: 0 : } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
1436 [ # # ]: 0 : if (ulp_blob_push_encap(blob, val, val_len) < 0) {
1437 : 0 : BNXT_TF_DBG(ERR, "encap blob push failed\n");
1438 : 0 : return -EINVAL;
1439 : : }
1440 [ # # ]: 0 : } else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) {
1441 : : /* do nothing */
1442 : : } else {
1443 [ # # ]: 0 : if (!ulp_blob_push(blob, val, val_len)) {
1444 : 0 : BNXT_TF_DBG(ERR, "push of val1 failed\n");
1445 : 0 : return -EINVAL;
1446 : : }
1447 : : }
1448 : 0 : *out_val = val;
1449 : 0 : return 0;
1450 : : }
1451 : :
1452 : : static int32_t
1453 : 0 : ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
1454 : : enum tf_dir dir,
1455 : : struct bnxt_ulp_mapper_field_info *fld,
1456 : : struct ulp_blob *blob,
1457 : : uint8_t is_key,
1458 : : const char *name)
1459 : : {
1460 : 0 : uint16_t write_idx = blob->write_idx;
1461 : 0 : uint8_t *val = NULL, *val1, *val2, *val3;
1462 : 0 : uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
1463 : : uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
1464 : : uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
1465 : 0 : uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
1466 : 0 : uint64_t value1 = 0, value2 = 0, value3 = 0;
1467 : : int32_t rc = 0;
1468 : :
1469 : : /* prepare the field source and values */
1470 [ # # ]: 0 : switch (fld->field_opc) {
1471 : : case BNXT_ULP_FIELD_OPC_SRC1:
1472 : : process_src1 = 1;
1473 : : break;
1474 : : case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1475 : : process_src1 = 1;
1476 : : break;
1477 : : case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1478 : : case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1479 : : process_src3 = 1;
1480 : : eval_src3 = 1;
1481 : : process_src1 = 1;
1482 : : process_src2 = 1;
1483 : : eval_src1 = 1;
1484 : : eval_src2 = 1;
1485 : : break;
1486 : : case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1487 : : case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1488 : : case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1489 : : case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1490 : : case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1491 : : case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1492 : : process_src1 = 1;
1493 : : process_src2 = 1;
1494 : : eval_src1 = 1;
1495 : : eval_src2 = 1;
1496 : : break;
1497 : : default:
1498 : : break;
1499 : : }
1500 : :
1501 : : /* process the src1 opcode */
1502 [ # # ]: 0 : if (process_src1) {
1503 [ # # ]: 0 : if (ulp_mapper_field_src_process(parms, fld->field_src1,
1504 : 0 : fld->field_opr1, dir, is_key,
1505 : 0 : fld->field_bit_size, &val1,
1506 : : &val1_len, &value1)) {
1507 : 0 : BNXT_TF_DBG(ERR, "fld src1 process failed\n");
1508 : 0 : goto error;
1509 : : }
1510 [ # # ]: 0 : if (eval_src1) {
1511 [ # # ]: 0 : if (ulp_mapper_field_buffer_eval(val1, val1_len,
1512 : : &val1_int)) {
1513 : 0 : BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
1514 : 0 : goto error;
1515 : : }
1516 : : }
1517 : : }
1518 : :
1519 : : /* for "if then clause" set the correct process */
1520 [ # # ]: 0 : if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
1521 [ # # ]: 0 : if (value1)
1522 : : process_src2 = 1;
1523 : : else
1524 : : process_src3 = 1;
1525 : : }
1526 : :
1527 : : /* process src2 opcode */
1528 [ # # ]: 0 : if (process_src2) {
1529 [ # # ]: 0 : if (ulp_mapper_field_src_process(parms, fld->field_src2,
1530 : 0 : fld->field_opr2, dir, is_key,
1531 : 0 : fld->field_bit_size, &val2,
1532 : : &val2_len, &value2)) {
1533 : 0 : BNXT_TF_DBG(ERR, "fld src2 process failed\n");
1534 : 0 : goto error;
1535 : : }
1536 [ # # ]: 0 : if (eval_src2) {
1537 [ # # ]: 0 : if (ulp_mapper_field_buffer_eval(val2, val2_len,
1538 : : &val2_int)) {
1539 : 0 : BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
1540 : 0 : goto error;
1541 : : }
1542 : : }
1543 : : }
1544 : :
1545 : : /* process src3 opcode */
1546 [ # # ]: 0 : if (process_src3) {
1547 [ # # ]: 0 : if (ulp_mapper_field_src_process(parms, fld->field_src3,
1548 : 0 : fld->field_opr3, dir, is_key,
1549 : 0 : fld->field_bit_size, &val3,
1550 : : &val3_len, &value3)) {
1551 : 0 : BNXT_TF_DBG(ERR, "fld src3 process failed\n");
1552 : 0 : goto error;
1553 : : }
1554 [ # # ]: 0 : if (eval_src3) {
1555 [ # # ]: 0 : if (ulp_mapper_field_buffer_eval(val3, val3_len,
1556 : : &val3_int)) {
1557 : 0 : BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
1558 : 0 : goto error;
1559 : : }
1560 : : }
1561 : : }
1562 : :
1563 : 0 : val_len = fld->field_bit_size;
1564 : : /* process the field opcodes */
1565 [ # # # # : 0 : switch (fld->field_opc) {
# # # # #
# ]
1566 : 0 : case BNXT_ULP_FIELD_OPC_SRC1:
1567 : 0 : rc = ulp_mapper_field_blob_write(fld->field_src1,
1568 : : blob, val1, val1_len, &val);
1569 : : val_len = val1_len;
1570 : 0 : break;
1571 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1572 [ # # ]: 0 : if (value1) {
1573 : 0 : rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
1574 : : val2, val2_len, &val);
1575 : : val_len = val2_len;
1576 : : } else {
1577 : 0 : rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
1578 : : val3, val3_len, &val);
1579 : : val_len = val3_len;
1580 : : }
1581 : : break;
1582 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1583 : : case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1584 : 0 : val_int = val1_int + val2_int;
1585 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1586 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1587 [ # # ]: 0 : if (!val)
1588 : : rc = -EINVAL;
1589 : : break;
1590 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1591 : : case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1592 : 0 : val_int = val1_int - val2_int;
1593 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1594 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1595 [ # # ]: 0 : if (!val)
1596 : : rc = -EINVAL;
1597 : : break;
1598 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1599 : 0 : val_int = val1_int | val2_int;
1600 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1601 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1602 [ # # ]: 0 : if (!val)
1603 : : rc = -EINVAL;
1604 : : break;
1605 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1606 : 0 : val_int = val1_int | val2_int | val3_int;
1607 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1608 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1609 [ # # ]: 0 : if (!val)
1610 : : rc = -EINVAL;
1611 : : break;
1612 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1613 : 0 : val_int = val1_int & val2_int;
1614 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1615 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1616 [ # # ]: 0 : if (!val)
1617 : : rc = -EINVAL;
1618 : : break;
1619 : 0 : case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1620 : 0 : val_int = val1_int & (val2_int | val3_int);
1621 [ # # ]: 0 : val_int = tfp_cpu_to_be_64(val_int);
1622 : 0 : val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1623 [ # # ]: 0 : if (!val)
1624 : : rc = -EINVAL;
1625 : : break;
1626 : : case BNXT_ULP_FIELD_OPC_SKIP:
1627 : : break;
1628 : 0 : default:
1629 : 0 : BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
1630 : : rc = -EINVAL;
1631 : : break;
1632 : : }
1633 : :
1634 [ # # ]: 0 : if (!rc)
1635 : 0 : return rc;
1636 : 0 : error:
1637 [ # # ]: 0 : BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
1638 : : fld->description, (val) ? write_idx : 0, val_len);
1639 : 0 : return -EINVAL;
1640 : : }
1641 : :
1642 : : /*
1643 : : * Result table process and fill the result blob.
1644 : : * data [out] - the result blob data
1645 : : */
1646 : : static int32_t
1647 [ # # ]: 0 : ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1648 : : struct bnxt_ulp_mapper_tbl_info *tbl,
1649 : : struct ulp_blob *data,
1650 : : const char *name)
1651 : : {
1652 : : struct bnxt_ulp_mapper_field_info *dflds;
1653 : : uint32_t i = 0, num_flds = 0, encap_flds = 0;
1654 : : struct ulp_blob encap_blob;
1655 : : int32_t rc = 0;
1656 : :
1657 : : /* Get the result field list */
1658 : : dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1659 : : &encap_flds);
1660 : :
1661 : : /* validate the result field list counts */
1662 [ # # # # ]: 0 : if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1663 [ # # # # : 0 : (!num_flds && !encap_flds)) || !dflds ||
# # ]
1664 [ # # ]: 0 : (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1665 [ # # ]: 0 : (!num_flds || encap_flds))) {
1666 : 0 : BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1667 : : num_flds, encap_flds);
1668 : 0 : return -EINVAL;
1669 : : }
1670 : :
1671 : : /* process the result fields */
1672 [ # # ]: 0 : for (i = 0; i < num_flds; i++) {
1673 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1674 : 0 : &dflds[i], data, 0, name);
1675 [ # # ]: 0 : if (rc) {
1676 : 0 : BNXT_TF_DBG(ERR, "result field processing failed\n");
1677 : 0 : return rc;
1678 : : }
1679 : : }
1680 : :
1681 : : /* process encap fields if any */
1682 [ # # ]: 0 : if (encap_flds) {
1683 : : uint32_t pad = 0;
1684 : : /* Initialize the encap blob */
1685 [ # # ]: 0 : if (!tbl->record_size &&
1686 [ # # ]: 0 : !parms->device_params->dynamic_sram_en) {
1687 : 0 : BNXT_TF_DBG(ERR, "Encap tbl record size incorrect\n");
1688 : 0 : return -EINVAL;
1689 : : }
1690 [ # # ]: 0 : if (!ulp_blob_init(&encap_blob,
1691 : : ULP_BYTE_2_BITS(tbl->record_size),
1692 : 0 : parms->device_params->encap_byte_order)) {
1693 : 0 : BNXT_TF_DBG(ERR, "blob inits failed.\n");
1694 : 0 : return -EINVAL;
1695 : : }
1696 [ # # ]: 0 : for (; i < encap_flds; i++) {
1697 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1698 : 0 : &dflds[i],
1699 : : &encap_blob, 0, name);
1700 [ # # ]: 0 : if (rc) {
1701 : 0 : BNXT_TF_DBG(ERR,
1702 : : "encap field processing failed\n");
1703 : 0 : return rc;
1704 : : }
1705 : : }
1706 : : /* add the dynamic pad push */
1707 [ # # ]: 0 : if (parms->device_params->dynamic_sram_en) {
1708 : 0 : uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size);
1709 : :
1710 : 0 : (void)ulp_mapper_dyn_tbl_type_get(parms, tbl,
1711 : : &encap_blob, &rec_s);
1712 : 0 : pad = rec_s - ulp_blob_data_len_get(&encap_blob);
1713 : : } else {
1714 : 0 : pad = ULP_BYTE_2_BITS(tbl->record_size) -
1715 : 0 : ulp_blob_data_len_get(&encap_blob);
1716 : : }
1717 [ # # ]: 0 : if (ulp_blob_pad_push(&encap_blob, pad) < 0) {
1718 : 0 : BNXT_TF_DBG(ERR, "encap buffer padding failed\n");
1719 : 0 : return -EINVAL;
1720 : : }
1721 : :
1722 : :
1723 : : /* perform the 64 bit byte swap */
1724 : 0 : ulp_blob_perform_64B_byte_swap(&encap_blob);
1725 : : /* Append encap blob to the result blob */
1726 : 0 : rc = ulp_blob_buffer_copy(data, &encap_blob);
1727 [ # # ]: 0 : if (rc) {
1728 : 0 : BNXT_TF_DBG(ERR, "encap buffer copy failed\n");
1729 : 0 : return rc;
1730 : : }
1731 : : }
1732 : : return rc;
1733 : : }
1734 : :
1735 : : static int32_t
1736 : 0 : ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1737 : : struct bnxt_ulp_mapper_tbl_info *tbl,
1738 : : uint64_t flow_id)
1739 : : {
1740 : : struct ulp_flow_db_res_params fid_parms;
1741 : : uint32_t mark, gfid, mark_flag;
1742 : 0 : enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1743 : : int32_t rc = 0;
1744 : :
1745 [ # # ]: 0 : if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1746 : : !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1747 [ # # ]: 0 : ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1748 : : BNXT_ULP_ACT_BIT_MARK)))
1749 : : return rc; /* no need to perform gfid process */
1750 : :
1751 : : /* Get the mark id details from action property */
1752 : 0 : memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1753 : : sizeof(mark));
1754 [ # # ]: 0 : mark = tfp_be_to_cpu_32(mark);
1755 : :
1756 : 0 : TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1757 : : mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1758 : :
1759 : 0 : rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1760 : : gfid, mark);
1761 [ # # ]: 0 : if (rc) {
1762 : 0 : BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1763 : 0 : return rc;
1764 : : }
1765 : 0 : fid_parms.direction = tbl->direction;
1766 : 0 : fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1767 : 0 : fid_parms.critical_resource = tbl->critical_resource;
1768 : 0 : fid_parms.resource_type = mark_flag;
1769 : 0 : fid_parms.resource_hndl = gfid;
1770 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1771 : :
1772 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1773 [ # # ]: 0 : if (rc)
1774 : 0 : BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1775 : : return rc;
1776 : : }
1777 : :
1778 : : static int32_t
1779 : 0 : ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1780 : : struct bnxt_ulp_mapper_tbl_info *tbl)
1781 : : {
1782 : : struct ulp_flow_db_res_params fid_parms;
1783 : : uint32_t act_idx, mark, mark_flag;
1784 : : uint64_t val64;
1785 : 0 : enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1786 : : int32_t rc = 0;
1787 : :
1788 [ # # ]: 0 : if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1789 : : !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1790 [ # # ]: 0 : ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1791 : : BNXT_ULP_ACT_BIT_MARK)))
1792 : : return rc; /* no need to perform mark action process */
1793 : :
1794 : : /* Get the mark id details from action property */
1795 : 0 : memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1796 : : sizeof(mark));
1797 [ # # ]: 0 : mark = tfp_be_to_cpu_32(mark);
1798 : :
1799 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
1800 : : BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1801 : : &val64)) {
1802 : 0 : BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1803 : 0 : return -EINVAL;
1804 : : }
1805 [ # # ]: 0 : act_idx = tfp_be_to_cpu_64(val64);
1806 : : mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1807 : 0 : rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1808 : : act_idx, mark);
1809 [ # # ]: 0 : if (rc) {
1810 : 0 : BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1811 : 0 : return rc;
1812 : : }
1813 : 0 : fid_parms.direction = tbl->direction;
1814 : 0 : fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1815 : 0 : fid_parms.critical_resource = tbl->critical_resource;
1816 : 0 : fid_parms.resource_type = mark_flag;
1817 : 0 : fid_parms.resource_hndl = act_idx;
1818 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1819 : :
1820 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1821 [ # # ]: 0 : if (rc)
1822 : 0 : BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1823 : : return rc;
1824 : : }
1825 : :
1826 : : static int32_t
1827 : 0 : ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1828 : : struct bnxt_ulp_mapper_tbl_info *tbl)
1829 : : {
1830 : : struct ulp_flow_db_res_params fid_parms;
1831 : : uint32_t act_idx, mark, mark_flag;
1832 : : uint64_t val64;
1833 : 0 : enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1834 : : int32_t rc = 0;
1835 : :
1836 [ # # ]: 0 : if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1837 : : mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1838 : : return rc; /* no need to perform mark action process */
1839 : :
1840 : : /* Get the mark id details from the computed field of dev port id */
1841 [ # # ]: 0 : mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1842 : :
1843 : : /* Get the main action pointer */
1844 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
1845 : : BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1846 : : &val64)) {
1847 : 0 : BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1848 : 0 : return -EINVAL;
1849 : : }
1850 [ # # ]: 0 : act_idx = tfp_be_to_cpu_64(val64);
1851 : :
1852 : : /* Set the mark flag to local fid and vfr flag */
1853 : : mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1854 : :
1855 : 0 : rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1856 : : act_idx, mark);
1857 [ # # ]: 0 : if (rc) {
1858 : 0 : BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1859 : 0 : return rc;
1860 : : }
1861 : 0 : fid_parms.direction = tbl->direction;
1862 : 0 : fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1863 : 0 : fid_parms.critical_resource = tbl->critical_resource;
1864 : 0 : fid_parms.resource_type = mark_flag;
1865 : 0 : fid_parms.resource_hndl = act_idx;
1866 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
1867 : :
1868 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1869 [ # # ]: 0 : if (rc)
1870 : 0 : BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1871 : : return rc;
1872 : : }
1873 : :
1874 : : /* Tcam table scan the identifier list and allocate each identifier */
1875 : : static int32_t
1876 [ # # ]: 0 : ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1877 : : struct bnxt_ulp_mapper_tbl_info *tbl)
1878 : : {
1879 : : struct bnxt_ulp_mapper_ident_info *idents;
1880 : : uint32_t num_idents;
1881 : : uint32_t i;
1882 : :
1883 : : idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1884 [ # # ]: 0 : for (i = 0; i < num_idents; i++) {
1885 [ # # ]: 0 : if (ulp_mapper_ident_process(parms, tbl,
1886 : 0 : &idents[i], NULL))
1887 : : return -EINVAL;
1888 : : }
1889 : : return 0;
1890 : : }
1891 : :
1892 : : /*
1893 : : * Tcam table scan the identifier list and extract the identifier from
1894 : : * the result blob.
1895 : : */
1896 : : static int32_t
1897 [ # # ]: 0 : ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1898 : : struct bnxt_ulp_mapper_tbl_info *tbl,
1899 : : struct ulp_blob *data)
1900 : : {
1901 : : struct bnxt_ulp_mapper_ident_info *idents;
1902 : : uint32_t num_idents = 0, i;
1903 : : int32_t rc = 0;
1904 : :
1905 : : /*
1906 : : * Extract the listed identifiers from the result field,
1907 : : * no need to allocate them.
1908 : : */
1909 : : idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1910 [ # # ]: 0 : for (i = 0; i < num_idents; i++) {
1911 : 0 : rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1912 [ # # ]: 0 : if (rc) {
1913 : 0 : BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1914 : 0 : return rc;
1915 : : }
1916 : : }
1917 : : return rc;
1918 : : }
1919 : :
1920 : : /* Internal function to write the tcam entry */
1921 : : static int32_t
1922 : 0 : ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1923 : : struct bnxt_ulp_mapper_tbl_info *tbl,
1924 : : struct ulp_blob *key,
1925 : : struct ulp_blob *mask,
1926 : : struct ulp_blob *data,
1927 : : uint16_t idx)
1928 : : {
1929 : 0 : struct tf_set_tcam_entry_parms sparms = { 0 };
1930 : : struct tf *tfp;
1931 : : uint16_t tmplen;
1932 : : int32_t rc;
1933 : :
1934 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
1935 [ # # ]: 0 : if (!tfp) {
1936 : 0 : BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1937 : 0 : return -EINVAL;
1938 : : }
1939 : :
1940 : 0 : sparms.dir = tbl->direction;
1941 : 0 : sparms.tcam_tbl_type = tbl->resource_type;
1942 : 0 : sparms.idx = idx;
1943 : 0 : sparms.key = ulp_blob_data_get(key, &tmplen);
1944 : 0 : sparms.key_sz_in_bits = tmplen;
1945 : 0 : sparms.mask = ulp_blob_data_get(mask, &tmplen);
1946 : 0 : sparms.result = ulp_blob_data_get(data, &tmplen);
1947 : 0 : sparms.result_sz_in_bits = tmplen;
1948 [ # # ]: 0 : if (tf_set_tcam_entry(tfp, &sparms)) {
1949 : 0 : BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1950 : : tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1951 : : tf_dir_2_str(sparms.dir), sparms.idx);
1952 : 0 : return -EIO;
1953 : : }
1954 : 0 : BNXT_TF_DBG(DEBUG, "tcam[%s][%s][%x] write success.\n",
1955 : : tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1956 : : tf_dir_2_str(sparms.dir), sparms.idx);
1957 : :
1958 : : /* Mark action */
1959 : 0 : rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1960 [ # # ]: 0 : if (rc) {
1961 : 0 : BNXT_TF_DBG(ERR, "failed mark action processing\n");
1962 : 0 : return rc;
1963 : : }
1964 : :
1965 : : return rc;
1966 : : }
1967 : :
1968 : : /*
1969 : : * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1970 : : *
1971 : : * parms [in] The mappers parms with data related to the flow.
1972 : : *
1973 : : * key [in] The original key to be transformed
1974 : : *
1975 : : * mask [in] The original mask to be transformed
1976 : : *
1977 : : * tkey [in/out] The transformed key
1978 : : *
1979 : : * tmask [in/out] The transformed mask
1980 : : *
1981 : : * returns zero on success, non-zero on failure
1982 : : */
1983 : : static uint32_t
1984 : 0 : ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1985 : : struct ulp_blob *key,
1986 : : struct ulp_blob *mask,
1987 : : struct ulp_blob *tkey,
1988 : : struct ulp_blob *tmask)
1989 : : {
1990 : : uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1991 : : uint32_t cword, i, rc;
1992 : : int32_t pad;
1993 : : uint8_t *val;
1994 : :
1995 : 0 : slice_width = dparms->wc_slice_width;
1996 : 0 : clen = dparms->wc_ctl_size_bits;
1997 : 0 : max_slices = dparms->wc_max_slices;
1998 : 0 : blen = ulp_blob_data_len_get(key);
1999 : :
2000 : : /* Get the length of the key based on number of slices and width */
2001 : : num_slices = 1;
2002 : : tlen = slice_width;
2003 : 0 : while (tlen < blen &&
2004 [ # # ]: 0 : num_slices <= max_slices) {
2005 : 0 : num_slices = num_slices << 1;
2006 : 0 : tlen = tlen << 1;
2007 : : }
2008 : :
2009 [ # # ]: 0 : if (num_slices > max_slices) {
2010 : 0 : BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
2011 : 0 : return -EINVAL;
2012 : : }
2013 : :
2014 : : /* The key/mask may not be on a natural slice boundary, pad it */
2015 : 0 : pad = tlen - blen;
2016 [ # # # # ]: 0 : if (ulp_blob_pad_push(key, pad) < 0 ||
2017 : 0 : ulp_blob_pad_push(mask, pad) < 0) {
2018 : 0 : BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
2019 : 0 : return -EINVAL;
2020 : : }
2021 : :
2022 : : /* The new length accounts for the ctrl word length and num slices */
2023 : 0 : tlen = tlen + clen * num_slices;
2024 [ # # # # ]: 0 : if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
2025 : 0 : !ulp_blob_init(tmask, tlen, mask->byte_order)) {
2026 : 0 : BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
2027 : 0 : return -EINVAL;
2028 : : }
2029 : :
2030 : : /* Build the transformed key/mask */
2031 : 0 : cword = dparms->wc_mode_list[num_slices - 1];
2032 [ # # ]: 0 : cword = tfp_cpu_to_be_32(cword);
2033 : : offset = 0;
2034 [ # # ]: 0 : for (i = 0; i < num_slices; i++) {
2035 : 0 : val = ulp_blob_push_32(tkey, &cword, clen);
2036 [ # # ]: 0 : if (!val) {
2037 : 0 : BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
2038 : 0 : return -EINVAL;
2039 : : }
2040 : 0 : val = ulp_blob_push_32(tmask, &cword, clen);
2041 [ # # ]: 0 : if (!val) {
2042 : 0 : BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
2043 : 0 : return -EINVAL;
2044 : : }
2045 : 0 : rc = ulp_blob_append(tkey, key, offset, slice_width);
2046 [ # # ]: 0 : if (rc) {
2047 : 0 : BNXT_TF_DBG(ERR, "Key blob append failed\n");
2048 : 0 : return rc;
2049 : : }
2050 : 0 : rc = ulp_blob_append(tmask, mask, offset, slice_width);
2051 [ # # ]: 0 : if (rc) {
2052 : 0 : BNXT_TF_DBG(ERR, "Mask blob append failed\n");
2053 : 0 : return rc;
2054 : : }
2055 : 0 : offset += slice_width;
2056 : : }
2057 : :
2058 : : /* The key/mask are byte reversed on every 4 byte chunk */
2059 : 0 : ulp_blob_perform_byte_reverse(tkey, 4);
2060 : 0 : ulp_blob_perform_byte_reverse(tmask, 4);
2061 : :
2062 : 0 : return 0;
2063 : : }
2064 : :
2065 : : /* internal function to post process the key/mask blobs for wildcard tcam tbl */
2066 : : static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
2067 : : {
2068 : 0 : ulp_blob_perform_64B_word_swap(blob);
2069 : 0 : ulp_blob_perform_64B_byte_swap(blob);
2070 : 0 : }
2071 : :
2072 : : static int32_t ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl)
2073 : : {
2074 [ # # # # ]: 0 : if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
2075 [ # # # # ]: 0 : tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
2076 : : tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW)
2077 : : return 1;
2078 : : return 0;
2079 : : }
2080 : :
2081 : : static int32_t
2082 : 0 : ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2083 : : struct bnxt_ulp_mapper_tbl_info *tbl)
2084 : : {
2085 : : struct bnxt_ulp_mapper_key_info *kflds;
2086 : : struct ulp_blob okey, omask, data, update_data;
2087 : : struct ulp_blob tkey, tmask; /* transform key and mask */
2088 : : struct ulp_blob *key, *mask;
2089 : : uint32_t i, num_kflds;
2090 : : struct tf *tfp;
2091 : : int32_t rc, trc;
2092 : 0 : struct bnxt_ulp_device_params *dparms = parms->device_params;
2093 : 0 : struct tf_alloc_tcam_entry_parms aparms = { 0 };
2094 : 0 : struct tf_search_tcam_entry_parms searchparms = { 0 };
2095 : 0 : struct ulp_flow_db_res_params fid_parms = { 0 };
2096 : 0 : struct tf_free_tcam_entry_parms free_parms = { 0 };
2097 : : uint32_t hit = 0;
2098 : 0 : uint16_t tmplen = 0;
2099 : : uint16_t idx;
2100 : : enum bnxt_ulp_byte_order key_byte_order;
2101 : :
2102 : : /* Set the key and mask to the original key and mask. */
2103 : : key = &okey;
2104 : : mask = &omask;
2105 : :
2106 : : /* Skip this if table opcode is NOP */
2107 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
2108 : : tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
2109 : 0 : BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
2110 : : tbl->tbl_opcode);
2111 : 0 : return 0;
2112 : : }
2113 : :
2114 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
2115 [ # # ]: 0 : if (!tfp) {
2116 : 0 : BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
2117 : 0 : return -EINVAL;
2118 : : }
2119 : :
2120 : : /* If only allocation of identifier then perform and exit */
2121 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) {
2122 : 0 : rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2123 : 0 : return rc;
2124 : : }
2125 : :
2126 : : kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2127 [ # # ]: 0 : if (!kflds || !num_kflds) {
2128 : 0 : BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2129 : 0 : return -EINVAL;
2130 : : }
2131 : :
2132 : : if (ulp_mapper_tcam_is_wc_tcam(tbl))
2133 : 0 : key_byte_order = dparms->wc_key_byte_order;
2134 : : else
2135 : 0 : key_byte_order = dparms->key_byte_order;
2136 : :
2137 [ # # # # ]: 0 : if (!ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) ||
2138 [ # # ]: 0 : !ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) ||
2139 : 0 : !ulp_blob_init(&data, tbl->result_bit_size,
2140 [ # # ]: 0 : dparms->result_byte_order) ||
2141 : 0 : !ulp_blob_init(&update_data, tbl->result_bit_size,
2142 : : dparms->result_byte_order)) {
2143 : 0 : BNXT_TF_DBG(ERR, "blob inits failed.\n");
2144 : 0 : return -EINVAL;
2145 : : }
2146 : :
2147 : : /* create the key/mask */
2148 : : /*
2149 : : * NOTE: The WC table will require some kind of flag to handle the
2150 : : * mode bits within the key/mask
2151 : : */
2152 [ # # ]: 0 : for (i = 0; i < num_kflds; i++) {
2153 : : /* Setup the key */
2154 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2155 : 0 : &kflds[i].field_info_spec,
2156 : : key, 1, "TCAM Key");
2157 [ # # ]: 0 : if (rc) {
2158 : 0 : BNXT_TF_DBG(ERR, "Key field set failed %s\n",
2159 : : kflds[i].field_info_spec.description);
2160 : 0 : return rc;
2161 : : }
2162 : :
2163 : : /* Setup the mask */
2164 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2165 : : &kflds[i].field_info_mask,
2166 : : mask, 0, "TCAM Mask");
2167 [ # # ]: 0 : if (rc) {
2168 : 0 : BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
2169 : : kflds[i].field_info_mask.description);
2170 : 0 : return rc;
2171 : : }
2172 : : }
2173 : :
2174 : : /* For wild card tcam perform the post process to swap the blob */
2175 : : if (ulp_mapper_tcam_is_wc_tcam(tbl)) {
2176 [ # # ]: 0 : if (dparms->wc_dynamic_pad_en) {
2177 : : /* Sets up the slices for writing to the WC TCAM */
2178 : 0 : rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
2179 : : key, mask,
2180 : : &tkey,
2181 : : &tmask);
2182 [ # # ]: 0 : if (rc) {
2183 : 0 : BNXT_TF_DBG(ERR,
2184 : : "Failed to post proc WC entry.\n");
2185 : 0 : return rc;
2186 : : }
2187 : : /* Now need to use the transform Key/Mask */
2188 : : key = &tkey;
2189 : : mask = &tmask;
2190 : : } else {
2191 : : ulp_mapper_wc_tcam_tbl_post_process(key);
2192 : : ulp_mapper_wc_tcam_tbl_post_process(mask);
2193 : : }
2194 : :
2195 : : }
2196 : :
2197 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2198 : : /* allocate the tcam index */
2199 : 0 : aparms.dir = tbl->direction;
2200 : 0 : aparms.tcam_tbl_type = tbl->resource_type;
2201 : 0 : aparms.key = ulp_blob_data_get(key, &tmplen);
2202 : 0 : aparms.key_sz_in_bits = tmplen;
2203 : 0 : aparms.mask = ulp_blob_data_get(mask, &tmplen);
2204 : :
2205 : : /* calculate the entry priority */
2206 : 0 : rc = ulp_mapper_priority_opc_process(parms, tbl,
2207 : : &aparms.priority);
2208 [ # # ]: 0 : if (rc) {
2209 : 0 : BNXT_TF_DBG(ERR, "entry priority process failed\n");
2210 : 0 : return rc;
2211 : : }
2212 : :
2213 : 0 : rc = tf_alloc_tcam_entry(tfp, &aparms);
2214 [ # # ]: 0 : if (rc) {
2215 : 0 : BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
2216 : 0 : return rc;
2217 : : }
2218 : 0 : idx = aparms.idx;
2219 : 0 : hit = aparms.hit;
2220 : : } else {
2221 : : /*
2222 : : * Searching before allocation to see if we already have an
2223 : : * entry. This allows re-use of a constrained resource.
2224 : : */
2225 : 0 : searchparms.dir = tbl->direction;
2226 : 0 : searchparms.tcam_tbl_type = tbl->resource_type;
2227 : 0 : searchparms.key = ulp_blob_data_get(key, &tmplen);
2228 : 0 : searchparms.key_sz_in_bits = tbl->key_bit_size;
2229 : 0 : searchparms.mask = ulp_blob_data_get(mask, &tmplen);
2230 : 0 : searchparms.alloc = 1;
2231 : 0 : searchparms.result = ulp_blob_data_get(&data, &tmplen);
2232 : 0 : searchparms.result_sz_in_bits = tbl->result_bit_size;
2233 : :
2234 : : /* calculate the entry priority */
2235 : 0 : rc = ulp_mapper_priority_opc_process(parms, tbl,
2236 : : &searchparms.priority);
2237 [ # # ]: 0 : if (rc) {
2238 : 0 : BNXT_TF_DBG(ERR, "entry priority process failed\n");
2239 : 0 : return rc;
2240 : : }
2241 : :
2242 : 0 : rc = tf_search_tcam_entry(tfp, &searchparms);
2243 [ # # ]: 0 : if (rc) {
2244 : 0 : BNXT_TF_DBG(ERR, "entry priority process failed\n");
2245 : 0 : return rc;
2246 : : }
2247 : :
2248 : : /* Successful search, check the result */
2249 [ # # ]: 0 : if (searchparms.search_status == REJECT) {
2250 : 0 : BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
2251 : 0 : return -ENOMEM;
2252 : : }
2253 : 0 : idx = searchparms.idx;
2254 : 0 : hit = searchparms.hit;
2255 : : }
2256 : :
2257 : : /* Write the tcam index into the regfile*/
2258 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
2259 [ # # ]: 0 : (uint64_t)tfp_cpu_to_be_64(idx))) {
2260 : 0 : BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2261 : : tbl->tbl_operand);
2262 : : rc = -EINVAL;
2263 : : /* Need to free the tcam idx, so goto error */
2264 : 0 : goto error;
2265 : : }
2266 : :
2267 : : /* if it is miss then it is same as no search before alloc */
2268 [ # # # # ]: 0 : if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2269 : : /*Scan identifier list, allocate identifier and update regfile*/
2270 : 0 : rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2271 : : /* Create the result blob */
2272 [ # # ]: 0 : if (!rc)
2273 : 0 : rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2274 : : "TCAM Result");
2275 : : /* write the tcam entry */
2276 [ # # ]: 0 : if (!rc)
2277 : 0 : rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
2278 : : mask, &data, idx);
2279 : : } else {
2280 : : /*Scan identifier list, extract identifier and update regfile*/
2281 : 0 : rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2282 : : }
2283 [ # # ]: 0 : if (rc)
2284 : 0 : goto error;
2285 : :
2286 : : /* Add the tcam index to the flow database */
2287 : 0 : fid_parms.direction = tbl->direction;
2288 : 0 : fid_parms.resource_func = tbl->resource_func;
2289 : 0 : fid_parms.resource_type = tbl->resource_type;
2290 : 0 : fid_parms.critical_resource = tbl->critical_resource;
2291 : 0 : fid_parms.resource_hndl = idx;
2292 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
2293 : :
2294 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2295 [ # # ]: 0 : if (rc) {
2296 : 0 : BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2297 : : rc);
2298 : : /* Need to free the identifier, so goto error */
2299 : 0 : goto error;
2300 : : }
2301 : :
2302 : : return 0;
2303 : 0 : error:
2304 : 0 : free_parms.dir = tbl->direction;
2305 : 0 : free_parms.tcam_tbl_type = tbl->resource_type;
2306 : 0 : free_parms.idx = idx;
2307 : 0 : trc = tf_free_tcam_entry(tfp, &free_parms);
2308 [ # # ]: 0 : if (trc)
2309 : 0 : BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2310 : : tbl->resource_type, tbl->direction, idx);
2311 : : return rc;
2312 : : }
2313 : :
2314 : : static int32_t
2315 : 0 : ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2316 : : struct bnxt_ulp_mapper_tbl_info *tbl)
2317 : : {
2318 : : struct bnxt_ulp_mapper_key_info *kflds;
2319 : : struct ulp_blob key, data;
2320 : : uint32_t i, num_kflds;
2321 : : uint16_t tmplen;
2322 : : struct tf *tfp;
2323 : 0 : struct ulp_flow_db_res_params fid_parms = { 0 };
2324 : 0 : struct tf_insert_em_entry_parms iparms = { 0 };
2325 : 0 : struct tf_delete_em_entry_parms free_parms = { 0 };
2326 : : enum bnxt_ulp_flow_mem_type mtype;
2327 : 0 : struct bnxt_ulp_device_params *dparms = parms->device_params;
2328 : : int32_t trc;
2329 : : int32_t rc = 0;
2330 : : int32_t pad = 0;
2331 : : enum bnxt_ulp_byte_order key_order, res_order;
2332 : :
2333 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
2334 : 0 : rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2335 [ # # ]: 0 : if (rc) {
2336 : 0 : BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2337 : 0 : return -EINVAL;
2338 : : }
2339 : :
2340 : : kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2341 [ # # ]: 0 : if (!kflds || !num_kflds) {
2342 : 0 : BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2343 : 0 : return -EINVAL;
2344 : : }
2345 : :
2346 : 0 : key_order = dparms->em_byte_order;
2347 : : res_order = dparms->em_byte_order;
2348 : :
2349 : : /* Initialize the key/result blobs */
2350 [ # # # # ]: 0 : if (!ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) ||
2351 : 0 : !ulp_blob_init(&data, tbl->result_bit_size, res_order)) {
2352 : 0 : BNXT_TF_DBG(ERR, "blob inits failed.\n");
2353 : 0 : return -EINVAL;
2354 : : }
2355 : :
2356 : : /* create the key */
2357 [ # # ]: 0 : for (i = 0; i < num_kflds; i++) {
2358 : : /* Setup the key */
2359 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2360 : 0 : &kflds[i].field_info_spec,
2361 : : &key, 1, "EM Key");
2362 [ # # ]: 0 : if (rc) {
2363 : 0 : BNXT_TF_DBG(ERR, "Key field set failed.\n");
2364 : 0 : return rc;
2365 : : }
2366 : : }
2367 : :
2368 : : /* if dynamic padding is enabled then add padding to result data */
2369 [ # # ]: 0 : if (dparms->em_dynamic_pad_en) {
2370 : : /* add padding to make sure key is at byte boundary */
2371 : 0 : ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2372 : :
2373 : : /* add the pad */
2374 : 0 : pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2375 [ # # ]: 0 : if (pad < 0) {
2376 : 0 : BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2377 : 0 : return -EINVAL;
2378 : : }
2379 : 0 : ulp_blob_pad_push(&data, (uint32_t)pad);
2380 : : }
2381 : :
2382 : : /* Create the result data blob */
2383 : 0 : rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2384 [ # # ]: 0 : if (rc) {
2385 : 0 : BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2386 : 0 : return rc;
2387 : : }
2388 [ # # ]: 0 : if (dparms->em_dynamic_pad_en) {
2389 : 0 : uint32_t abits = dparms->em_blk_align_bits;
2390 : :
2391 : : /* when dynamic padding is enabled merge result + key */
2392 : 0 : rc = ulp_blob_block_merge(&data, &key, abits, pad);
2393 [ # # ]: 0 : if (rc) {
2394 : 0 : BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2395 : 0 : return rc;
2396 : : }
2397 : :
2398 : : /* add padding to make sure merged result is at slice boundary*/
2399 : 0 : ulp_blob_pad_align(&data, abits);
2400 : :
2401 : 0 : ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2402 : : }
2403 : :
2404 : : /* do the transpose for the internal EM keys */
2405 [ # # ]: 0 : if (tbl->resource_type == TF_MEM_INTERNAL) {
2406 [ # # ]: 0 : if (dparms->em_key_align_bytes) {
2407 : 0 : int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2408 : :
2409 : 0 : tmplen = ulp_blob_data_len_get(&key);
2410 : 0 : ulp_blob_pad_push(&key, b - tmplen);
2411 : : }
2412 : 0 : tmplen = ulp_blob_data_len_get(&key);
2413 : 0 : ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2414 : : }
2415 : :
2416 : 0 : rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2417 : : &iparms.tbl_scope_id);
2418 [ # # ]: 0 : if (rc) {
2419 : 0 : BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2420 : 0 : return rc;
2421 : : }
2422 : :
2423 : : /*
2424 : : * NOTE: the actual blob size will differ from the size in the tbl
2425 : : * entry due to the padding.
2426 : : */
2427 : 0 : iparms.dup_check = 0;
2428 : 0 : iparms.dir = tbl->direction;
2429 : 0 : iparms.mem = tbl->resource_type;
2430 : 0 : iparms.key = ulp_blob_data_get(&key, &tmplen);
2431 : 0 : iparms.key_sz_in_bits = tbl->key_bit_size;
2432 : 0 : iparms.em_record = ulp_blob_data_get(&data, &tmplen);
2433 [ # # ]: 0 : if (tbl->result_bit_size)
2434 : 0 : iparms.em_record_sz_in_bits = tbl->result_bit_size;
2435 : : else
2436 : 0 : iparms.em_record_sz_in_bits = tmplen;
2437 : :
2438 : 0 : rc = tf_insert_em_entry(tfp, &iparms);
2439 [ # # ]: 0 : if (rc) {
2440 : 0 : BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2441 : 0 : return rc;
2442 : : }
2443 : :
2444 : : /* Mark action process */
2445 [ # # ]: 0 : if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2446 [ # # ]: 0 : tbl->resource_type == TF_MEM_EXTERNAL)
2447 : 0 : rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2448 [ # # ]: 0 : else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2449 [ # # ]: 0 : tbl->resource_type == TF_MEM_INTERNAL)
2450 : 0 : rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2451 [ # # ]: 0 : if (rc) {
2452 : 0 : BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2453 : 0 : goto error;
2454 : : }
2455 : :
2456 : : /* Link the EM resource to the flow in the flow db */
2457 : : memset(&fid_parms, 0, sizeof(fid_parms));
2458 : 0 : fid_parms.direction = tbl->direction;
2459 : 0 : fid_parms.resource_func = tbl->resource_func;
2460 : 0 : fid_parms.resource_type = tbl->resource_type;
2461 : 0 : fid_parms.critical_resource = tbl->critical_resource;
2462 : 0 : fid_parms.resource_hndl = iparms.flow_handle;
2463 : :
2464 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2465 [ # # ]: 0 : if (rc) {
2466 : 0 : BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2467 : : rc);
2468 : : /* Need to free the identifier, so goto error */
2469 : 0 : goto error;
2470 : : }
2471 : :
2472 : : return 0;
2473 : 0 : error:
2474 : 0 : free_parms.dir = iparms.dir;
2475 : 0 : free_parms.mem = iparms.mem;
2476 : 0 : free_parms.tbl_scope_id = iparms.tbl_scope_id;
2477 : 0 : free_parms.flow_handle = iparms.flow_handle;
2478 : :
2479 : 0 : trc = tf_delete_em_entry(tfp, &free_parms);
2480 [ # # ]: 0 : if (trc)
2481 : 0 : BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2482 : :
2483 : : return rc;
2484 : : }
2485 : :
2486 : : static int32_t
2487 : 0 : ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2488 : : struct bnxt_ulp_mapper_tbl_info *tbl)
2489 : : {
2490 : : struct ulp_flow_db_res_params fid_parms;
2491 : : struct ulp_blob data;
2492 : 0 : uint64_t regval = 0;
2493 : : uint16_t tmplen;
2494 : : uint32_t index;
2495 : : int32_t rc = 0, trc = 0;
2496 : 0 : struct tf_alloc_tbl_entry_parms aparms = { 0 };
2497 : 0 : struct tf_set_tbl_entry_parms sparms = { 0 };
2498 : 0 : struct tf_get_tbl_entry_parms gparms = { 0 };
2499 : 0 : struct tf_free_tbl_entry_parms free_parms = { 0 };
2500 : : uint32_t tbl_scope_id;
2501 : : struct tf *tfp;
2502 : : struct bnxt_ulp_glb_resource_info glb_res = { 0 };
2503 : : uint16_t bit_size;
2504 : : bool alloc = false;
2505 : : bool write = false;
2506 : : bool global = false;
2507 : : uint64_t act_rec_size;
2508 : : bool shared = false;
2509 : 0 : enum tf_tbl_type tbl_type = tbl->resource_type;
2510 : :
2511 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
2512 : : /* compute the blob size */
2513 : : bit_size = ulp_mapper_dyn_blob_size_get(parms, tbl);
2514 : :
2515 : : /* Initialize the blob data */
2516 [ # # ]: 0 : if (!ulp_blob_init(&data, bit_size,
2517 : : parms->device_params->result_byte_order)) {
2518 : 0 : BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2519 : 0 : return -EINVAL;
2520 : : }
2521 : :
2522 : : /* Get the scope id first */
2523 : 0 : rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2524 [ # # ]: 0 : if (rc) {
2525 : 0 : BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2526 : 0 : return rc;
2527 : : }
2528 : :
2529 [ # # # # : 0 : switch (tbl->tbl_opcode) {
# # # ]
2530 : : case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2531 : : alloc = true;
2532 : : break;
2533 : 0 : case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2534 : : /*
2535 : : * Build the entry, alloc an index, write the table, and store
2536 : : * the data in the regfile.
2537 : : */
2538 : : alloc = true;
2539 : : write = true;
2540 : 0 : break;
2541 : 0 : case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2542 : : /*
2543 : : * get the index to write to from the regfile and then write
2544 : : * the table entry.
2545 : : */
2546 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
2547 : 0 : tbl->tbl_operand,
2548 : : ®val)) {
2549 : 0 : BNXT_TF_DBG(ERR,
2550 : : "Failed to get tbl idx from regfile[%d].\n",
2551 : : tbl->tbl_operand);
2552 : 0 : return -EINVAL;
2553 : : }
2554 [ # # ]: 0 : index = tfp_be_to_cpu_64(regval);
2555 : : /* For external, we need to reverse shift */
2556 [ # # ]: 0 : if (tbl->resource_type == TF_TBL_TYPE_EXT)
2557 : 0 : index = TF_ACT_REC_PTR_2_OFFSET(index);
2558 : :
2559 : : write = true;
2560 : : break;
2561 : 0 : case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2562 : : /*
2563 : : * Build the entry, alloc an index, write the table, and store
2564 : : * the data in the global regfile.
2565 : : */
2566 : : alloc = true;
2567 : : global = true;
2568 : : write = true;
2569 : 0 : glb_res.direction = tbl->direction;
2570 : 0 : glb_res.resource_func = tbl->resource_func;
2571 : 0 : glb_res.resource_type = tbl->resource_type;
2572 : 0 : glb_res.glb_regfile_index = tbl->tbl_operand;
2573 : 0 : break;
2574 : 0 : case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2575 [ # # ]: 0 : if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2576 : 0 : BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2577 : 0 : return -EINVAL;
2578 : : }
2579 : : /*
2580 : : * get the index to write to from the global regfile and then
2581 : : * write the table.
2582 : : */
2583 : 0 : if (ulp_mapper_glb_resource_read(parms->mapper_data,
2584 : 0 : tbl->direction,
2585 [ # # ]: 0 : tbl->tbl_operand,
2586 : : ®val, &shared)) {
2587 : 0 : BNXT_TF_DBG(ERR,
2588 : : "Failed to get tbl idx from Glb RF[%d].\n",
2589 : : tbl->tbl_operand);
2590 : 0 : return -EINVAL;
2591 : : }
2592 [ # # ]: 0 : index = tfp_be_to_cpu_64(regval);
2593 : : /* For external, we need to reverse shift */
2594 [ # # ]: 0 : if (tbl->resource_type == TF_TBL_TYPE_EXT)
2595 : 0 : index = TF_ACT_REC_PTR_2_OFFSET(index);
2596 : : write = true;
2597 : : break;
2598 : 0 : case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2599 : : /*
2600 : : * The read is different from the rest and can be handled here
2601 : : * instead of trying to use common code. Simply read the table
2602 : : * with the index from the regfile, scan and store the
2603 : : * identifiers, and return.
2604 : : */
2605 [ # # ]: 0 : if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2606 : : /* Not currently supporting with EXT */
2607 : 0 : BNXT_TF_DBG(ERR,
2608 : : "Ext Table Read Opcode not supported.\n");
2609 : 0 : return -EINVAL;
2610 : : }
2611 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
2612 : 0 : tbl->tbl_operand, ®val)) {
2613 : 0 : BNXT_TF_DBG(ERR,
2614 : : "Failed to get tbl idx from regfile[%d]\n",
2615 : : tbl->tbl_operand);
2616 : 0 : return -EINVAL;
2617 : : }
2618 [ # # ]: 0 : index = tfp_be_to_cpu_64(regval);
2619 : 0 : gparms.dir = tbl->direction;
2620 : 0 : gparms.type = tbl->resource_type;
2621 : 0 : gparms.data = ulp_blob_data_get(&data, &tmplen);
2622 : 0 : gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2623 : 0 : gparms.idx = index;
2624 : 0 : rc = tf_get_tbl_entry(tfp, &gparms);
2625 [ # # ]: 0 : if (rc) {
2626 : 0 : BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2627 : : tbl->resource_type, index);
2628 : 0 : return rc;
2629 : : }
2630 : : /*
2631 : : * Scan the fields in the entry and push them into the regfile.
2632 : : */
2633 : 0 : rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2634 : : gparms.data,
2635 : 0 : gparms.data_sz_in_bytes,
2636 : : data.byte_order);
2637 [ # # ]: 0 : if (rc) {
2638 : 0 : BNXT_TF_DBG(ERR,
2639 : : "Failed to get flds on tbl read rc=%d\n",
2640 : : rc);
2641 : 0 : return rc;
2642 : : }
2643 : : return 0;
2644 : 0 : default:
2645 : 0 : BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2646 : : tbl->tbl_opcode);
2647 : 0 : return -EINVAL;
2648 : : }
2649 : :
2650 [ # # ]: 0 : if (write) {
2651 : : /* Get the result fields list */
2652 : 0 : rc = ulp_mapper_tbl_result_build(parms,
2653 : : tbl,
2654 : : &data,
2655 : : "Indexed Result");
2656 [ # # ]: 0 : if (rc) {
2657 : 0 : BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2658 : 0 : return rc;
2659 : : }
2660 : : }
2661 : :
2662 [ # # ]: 0 : if (alloc) {
2663 : 0 : aparms.dir = tbl->direction;
2664 : 0 : tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl,
2665 : : &data, &tmplen);
2666 : 0 : aparms.type = tbl_type;
2667 : 0 : aparms.tbl_scope_id = tbl_scope_id;
2668 : :
2669 : : /* All failures after the alloc succeeds require a free */
2670 : 0 : rc = tf_alloc_tbl_entry(tfp, &aparms);
2671 [ # # ]: 0 : if (rc) {
2672 : 0 : BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2673 : : tf_tbl_type_2_str(aparms.type),
2674 : : tf_dir_2_str(tbl->direction), rc);
2675 : 0 : return rc;
2676 : : }
2677 : 0 : index = aparms.idx;
2678 : :
2679 : : /*
2680 : : * Store the index in the regfile since we either allocated it
2681 : : * or it was a hit.
2682 : : *
2683 : : * Calculate the idx for the result record, for external EM the
2684 : : * offset needs to be shifted accordingly.
2685 : : * If external non-inline table types are used then need to
2686 : : * revisit this logic.
2687 : : */
2688 [ # # ]: 0 : if (tbl->resource_type == TF_TBL_TYPE_EXT)
2689 : 0 : regval = TF_ACT_REC_OFFSET_2_PTR(index);
2690 : : else
2691 : 0 : regval = index;
2692 [ # # ]: 0 : regval = tfp_cpu_to_be_64(regval);
2693 : :
2694 [ # # ]: 0 : if (global) {
2695 : : /*
2696 : : * Shared resources are never allocated through this
2697 : : * method, so the shared flag is always false.
2698 : : */
2699 [ # # ]: 0 : rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2700 : : &glb_res, regval,
2701 : : false);
2702 : : } else {
2703 : 0 : rc = ulp_regfile_write(parms->regfile,
2704 : 0 : tbl->tbl_operand, regval);
2705 : : }
2706 [ # # ]: 0 : if (rc) {
2707 [ # # ]: 0 : BNXT_TF_DBG(ERR,
2708 : : "Failed to write %s regfile[%d] rc=%d\n",
2709 : : (global) ? "global" : "reg",
2710 : : tbl->tbl_operand, rc);
2711 : 0 : goto error;
2712 : : }
2713 : : }
2714 : :
2715 [ # # ]: 0 : if (write) {
2716 : 0 : sparms.dir = tbl->direction;
2717 : 0 : sparms.data = ulp_blob_data_get(&data, &tmplen);
2718 : 0 : tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, &data,
2719 : : &tmplen);
2720 : 0 : sparms.type = tbl_type;
2721 : 0 : sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2722 : 0 : sparms.idx = index;
2723 : 0 : sparms.tbl_scope_id = tbl_scope_id;
2724 [ # # ]: 0 : if (shared)
2725 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx,
2726 : : tbl->session_type);
2727 : 0 : rc = tf_set_tbl_entry(tfp, &sparms);
2728 [ # # ]: 0 : if (rc) {
2729 : 0 : BNXT_TF_DBG(ERR,
2730 : : "Index table[%s][%s][%x] write fail rc=%d\n",
2731 : : tf_tbl_type_2_str(sparms.type),
2732 : : tf_dir_2_str(sparms.dir),
2733 : : sparms.idx, rc);
2734 : 0 : goto error;
2735 : : }
2736 : 0 : BNXT_TF_DBG(DEBUG, "Index table[%s][%s][%x] write successful\n",
2737 : : tf_tbl_type_2_str(sparms.type),
2738 : : tf_dir_2_str(sparms.dir), sparms.idx);
2739 : :
2740 : : /* Calculate action record size */
2741 [ # # ]: 0 : if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2742 : 0 : act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2743 : 0 : act_rec_size--;
2744 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile,
2745 : : BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2746 [ # # ]: 0 : tfp_cpu_to_be_64(act_rec_size)))
2747 : 0 : BNXT_TF_DBG(ERR,
2748 : : "Failed write the act rec size\n");
2749 : : }
2750 : : }
2751 : :
2752 : : /* Link the resource to the flow in the flow db */
2753 : : memset(&fid_parms, 0, sizeof(fid_parms));
2754 : 0 : fid_parms.direction = tbl->direction;
2755 : 0 : fid_parms.resource_func = tbl->resource_func;
2756 : 0 : fid_parms.resource_type = tbl_type;
2757 : 0 : fid_parms.resource_sub_type = tbl->resource_sub_type;
2758 : 0 : fid_parms.resource_hndl = index;
2759 : 0 : fid_parms.critical_resource = tbl->critical_resource;
2760 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
2761 : :
2762 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2763 [ # # ]: 0 : if (rc) {
2764 : 0 : BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2765 : : rc);
2766 : 0 : goto error;
2767 : : }
2768 : :
2769 : : /* Perform the VF rep action */
2770 : 0 : rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2771 [ # # ]: 0 : if (rc) {
2772 : 0 : BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2773 : 0 : goto error;
2774 : : }
2775 : : return rc;
2776 : 0 : error:
2777 : : /* Shared resources are not freed */
2778 [ # # ]: 0 : if (shared)
2779 : : return rc;
2780 : : /*
2781 : : * Free the allocated resource since we failed to either
2782 : : * write to the entry or link the flow
2783 : : */
2784 : 0 : free_parms.dir = tbl->direction;
2785 : 0 : free_parms.type = tbl_type;
2786 : 0 : free_parms.idx = index;
2787 : 0 : free_parms.tbl_scope_id = tbl_scope_id;
2788 : :
2789 : 0 : trc = tf_free_tbl_entry(tfp, &free_parms);
2790 [ # # ]: 0 : if (trc)
2791 : 0 : BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2792 : :
2793 : : return rc;
2794 : : }
2795 : :
2796 : : static int32_t
2797 : 0 : ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2798 : : struct bnxt_ulp_mapper_tbl_info *tbl)
2799 : : {
2800 : : struct ulp_blob data, res_blob;
2801 : : uint64_t idx;
2802 : : uint16_t tmplen;
2803 : : int32_t rc = 0;
2804 : 0 : struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2805 : 0 : struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2806 : : struct tf *tfp;
2807 : 0 : enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2808 : : uint32_t res_size;
2809 : :
2810 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type);
2811 : : /* Initialize the blob data */
2812 [ # # ]: 0 : if (!ulp_blob_init(&data, tbl->result_bit_size,
2813 : 0 : parms->device_params->result_byte_order)) {
2814 : 0 : BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2815 : 0 : return -EINVAL;
2816 : : }
2817 : :
2818 : : /* create the result blob */
2819 : 0 : rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2820 [ # # ]: 0 : if (rc) {
2821 : 0 : BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2822 : 0 : return rc;
2823 : : }
2824 : :
2825 : : /* Get the index details */
2826 [ # # # # : 0 : switch (if_opc) {
# # ]
2827 : 0 : case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2828 [ # # ]: 0 : idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2829 : 0 : break;
2830 : 0 : case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2831 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2832 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2833 : : tbl->tbl_operand);
2834 : 0 : return -EINVAL;
2835 : : }
2836 [ # # ]: 0 : idx = tfp_be_to_cpu_64(idx);
2837 : 0 : break;
2838 : 0 : case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2839 : 0 : idx = tbl->tbl_operand;
2840 : 0 : break;
2841 : 0 : case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2842 : : /* Initialize the result blob */
2843 [ # # ]: 0 : if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2844 : 0 : parms->device_params->result_byte_order)) {
2845 : 0 : BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2846 : 0 : return -EINVAL;
2847 : : }
2848 : :
2849 : : /* read the interface table */
2850 [ # # ]: 0 : idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2851 : 0 : res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2852 : 0 : get_parms.dir = tbl->direction;
2853 : 0 : get_parms.type = tbl->resource_type;
2854 : 0 : get_parms.idx = idx;
2855 : 0 : get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2856 : 0 : get_parms.data_sz_in_bytes = res_size;
2857 : :
2858 : 0 : rc = tf_get_if_tbl_entry(tfp, &get_parms);
2859 [ # # ]: 0 : if (rc) {
2860 : 0 : BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2861 : : get_parms.type,
2862 : : tf_dir_2_str(get_parms.dir),
2863 : : get_parms.idx, rc);
2864 : 0 : return rc;
2865 : : }
2866 : 0 : rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2867 : : res_blob.data,
2868 : : res_size,
2869 : : res_blob.byte_order);
2870 [ # # ]: 0 : if (rc)
2871 : 0 : BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2872 : : return rc;
2873 : : case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2874 : : return rc; /* skip it */
2875 : 0 : default:
2876 : 0 : BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2877 : 0 : return -EINVAL;
2878 : : }
2879 : :
2880 : : /* Perform the tf table set by filling the set params */
2881 : 0 : iftbl_params.dir = tbl->direction;
2882 : 0 : iftbl_params.type = tbl->resource_type;
2883 : 0 : iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2884 : 0 : iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2885 : 0 : iftbl_params.idx = idx;
2886 : :
2887 : 0 : rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2888 [ # # ]: 0 : if (rc) {
2889 : 0 : BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2890 : : iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2891 : : tf_dir_2_str(iftbl_params.dir),
2892 : : iftbl_params.idx, rc);
2893 : 0 : return rc;
2894 : : }
2895 : : BNXT_TF_INF("Set table[%s][%s][%x] success.\n",
2896 : : tf_if_tbl_2_str(iftbl_params.type),
2897 : : tf_dir_2_str(iftbl_params.dir),
2898 : : iftbl_params.idx);
2899 : :
2900 : : /*
2901 : : * TBD: Need to look at the need to store idx in flow db for restore
2902 : : * the table to its original state on deletion of this entry.
2903 : : */
2904 : : return rc;
2905 : : }
2906 : :
2907 : : static int32_t
2908 : 0 : ulp_mapper_gen_tbl_ref_cnt_process(struct bnxt_ulp_mapper_parms *parms,
2909 : : struct bnxt_ulp_mapper_tbl_info *tbl,
2910 : : struct ulp_mapper_gen_tbl_entry *entry)
2911 : : {
2912 : : int32_t rc = 0;
2913 : : uint64_t val64;
2914 : :
2915 : : /* Allow the template to manage the reference count */
2916 [ # # # # : 0 : switch (tbl->ref_cnt_opcode) {
# ]
2917 : 0 : case BNXT_ULP_REF_CNT_OPC_INC:
2918 : 0 : ULP_GEN_TBL_REF_CNT_INC(entry);
2919 : 0 : break;
2920 : 0 : case BNXT_ULP_REF_CNT_OPC_DEC:
2921 : : /* writes never decrement the ref count */
2922 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_WRITE)
2923 : : return -EINVAL;
2924 : :
2925 : 0 : ULP_GEN_TBL_REF_CNT_DEC(entry);
2926 : 0 : break;
2927 : : case BNXT_ULP_REF_CNT_OPC_NOP:
2928 : : /* Nothing to be done, generally used when
2929 : : * template gets the ref_cnt to make a decision
2930 : : */
2931 : : break;
2932 : 0 : case BNXT_ULP_REF_CNT_OPC_DEFAULT:
2933 : : /* This is the default case and is backward
2934 : : * compatible with older templates
2935 : : */
2936 [ # # ]: 0 : if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP)
2937 : 0 : ULP_GEN_TBL_REF_CNT_INC(entry);
2938 : : break;
2939 : 0 : default:
2940 : 0 : BNXT_TF_DBG(ERR, "Invalid REF_CNT_OPC %d\n",
2941 : : tbl->ref_cnt_opcode);
2942 : 0 : return -EINVAL;
2943 : : }
2944 : :
2945 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_READ) {
2946 : : /* Add ref_cnt to the regfile for template to use. */
2947 : 0 : val64 = (uint32_t)ULP_GEN_TBL_REF_CNT(entry);
2948 [ # # ]: 0 : val64 = tfp_cpu_to_be_64(val64);
2949 : 0 : rc = ulp_regfile_write(parms->regfile,
2950 : : BNXT_ULP_RF_IDX_REF_CNT,
2951 : : val64);
2952 [ # # ]: 0 : if (rc) {
2953 : 0 : BNXT_TF_DBG(ERR,
2954 : : "Failed to write regfile[ref_cnt]\n");
2955 : 0 : return rc;
2956 : : }
2957 : : }
2958 : :
2959 : : return rc;
2960 : : }
2961 : :
2962 : : static int32_t
2963 : 0 : ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2964 : : struct bnxt_ulp_mapper_tbl_info *tbl)
2965 : : {
2966 : : struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2967 : : struct bnxt_ulp_mapper_key_info *kflds;
2968 : : struct ulp_flow_db_res_params fid_parms;
2969 : : struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2970 : : struct ulp_gen_hash_entry_params hash_entry;
2971 : 0 : uint16_t tmplen = 0;
2972 : : struct ulp_blob key, data;
2973 : : uint8_t *cache_key;
2974 : : int32_t tbl_idx;
2975 [ # # ]: 0 : uint32_t i, num_kflds = 0, key_index = 0;
2976 : : uint32_t gen_tbl_miss = 1, fdb_write = 0;
2977 : : uint8_t *byte_data;
2978 : : int32_t rc = 0;
2979 : :
2980 : : /* Get the key fields list and build the key. */
2981 : : kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2982 [ # # ]: 0 : if (!kflds || !num_kflds) {
2983 : 0 : BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2984 : 0 : return -EINVAL;
2985 : : }
2986 : :
2987 [ # # ]: 0 : if (!ulp_blob_init(&key, tbl->key_bit_size,
2988 : : parms->device_params->key_byte_order)) {
2989 : 0 : BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2990 : 0 : return -EINVAL;
2991 : : }
2992 [ # # ]: 0 : for (i = 0; i < num_kflds; i++) {
2993 : : /* Setup the key */
2994 : 0 : rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2995 : 0 : &kflds[i].field_info_spec,
2996 : : &key, 1, "Gen Tbl Key");
2997 [ # # ]: 0 : if (rc) {
2998 : 0 : BNXT_TF_DBG(ERR,
2999 : : "Failed to create key for Gen tbl rc=%d\n",
3000 : : rc);
3001 : 0 : return -EINVAL;
3002 : : }
3003 : : }
3004 : :
3005 : : /* Calculate the table index for the generic table*/
3006 : 0 : tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
3007 : 0 : tbl->direction);
3008 [ # # ]: 0 : if (tbl_idx < 0) {
3009 : 0 : BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
3010 : : tbl->resource_sub_type, tbl->direction);
3011 : 0 : return -EINVAL;
3012 : : }
3013 : :
3014 : : /* The_key is a byte array convert it to a search index */
3015 : 0 : cache_key = ulp_blob_data_get(&key, &tmplen);
3016 : :
3017 : : /* get the generic table */
3018 : 0 : gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
3019 : :
3020 : : /* Check if generic hash table */
3021 [ # # ]: 0 : if (gen_tbl_list->hash_tbl) {
3022 [ # # ]: 0 : if (tbl->gen_tbl_lkup_type !=
3023 : : BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
3024 : 0 : BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
3025 : : gen_tbl_list->gen_tbl_name);
3026 : 0 : return -EINVAL;
3027 : : }
3028 : 0 : hash_entry.key_data = cache_key;
3029 : 0 : hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
3030 : 0 : rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
3031 : : &hash_entry);
3032 [ # # ]: 0 : if (rc) {
3033 : 0 : BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
3034 : : gen_tbl_list->gen_tbl_name);
3035 : 0 : return rc;
3036 : : }
3037 [ # # ]: 0 : if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
3038 : 0 : key_index = hash_entry.key_idx;
3039 : : /* Get the generic table entry */
3040 [ # # ]: 0 : if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
3041 : : key_index,
3042 : : &gen_tbl_ent))
3043 : : return -EINVAL;
3044 : : /* store the hash index in the fdb */
3045 : 0 : key_index = hash_entry.hash_index;
3046 : : }
3047 : : } else {
3048 : : /* convert key to index directly */
3049 [ # # ]: 0 : if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) {
3050 : 0 : BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n",
3051 : : gen_tbl_list->gen_tbl_name);
3052 : 0 : return -EINVAL;
3053 : : }
3054 : 0 : memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
3055 : : /* Get the generic table entry */
3056 [ # # ]: 0 : if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
3057 : : &gen_tbl_ent))
3058 : : return -EINVAL;
3059 : : }
3060 [ # # # ]: 0 : switch (tbl->tbl_opcode) {
3061 : 0 : case BNXT_ULP_GENERIC_TBL_OPC_READ:
3062 [ # # ]: 0 : if (gen_tbl_list->hash_tbl) {
3063 [ # # ]: 0 : if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
3064 : : break; /* nothing to be done , no entry */
3065 : : }
3066 : :
3067 : : /* check the reference count */
3068 [ # # ]: 0 : if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
3069 : : g = &gen_tbl_ent;
3070 : : /* Scan ident list and create the result blob*/
3071 : 0 : rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
3072 : : g->byte_data,
3073 : : g->byte_data_size,
3074 : : g->byte_order);
3075 [ # # ]: 0 : if (rc) {
3076 : 0 : BNXT_TF_DBG(ERR,
3077 : : "Failed to scan ident list\n");
3078 : 0 : return -EINVAL;
3079 : : }
3080 : :
3081 : : /* it is a hit */
3082 : : gen_tbl_miss = 0;
3083 : : fdb_write = 1;
3084 : : }
3085 : : break;
3086 : 0 : case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
3087 [ # # ]: 0 : if (gen_tbl_list->hash_tbl) {
3088 : 0 : rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
3089 : : &hash_entry,
3090 : : &gen_tbl_ent);
3091 [ # # ]: 0 : if (rc)
3092 : : return rc;
3093 : : /* store the hash index in the fdb */
3094 : 0 : key_index = hash_entry.hash_index;
3095 : : }
3096 : :
3097 : : /* check the reference count and ignore ref_cnt if NOP.
3098 : : * NOP allows a write as an update.
3099 : : */
3100 : :
3101 [ # # ]: 0 : if (tbl->ref_cnt_opcode != BNXT_ULP_REF_CNT_OPC_NOP &&
3102 [ # # ]: 0 : ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
3103 : : /* a hit then error */
3104 : 0 : BNXT_TF_DBG(ERR, "generic entry already present\n");
3105 : 0 : return -EINVAL; /* success */
3106 : : }
3107 : :
3108 : : /* Initialize the blob data */
3109 [ # # ]: 0 : if (!ulp_blob_init(&data, tbl->result_bit_size,
3110 : : gen_tbl_ent.byte_order)) {
3111 : 0 : BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
3112 : 0 : return -EINVAL;
3113 : : }
3114 : :
3115 : : /* Get the result fields list */
3116 : 0 : rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
3117 : : "Gen tbl Result");
3118 [ # # ]: 0 : if (rc) {
3119 : 0 : BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
3120 : 0 : return rc;
3121 : : }
3122 : 0 : byte_data = ulp_blob_data_get(&data, &tmplen);
3123 : 0 : rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
3124 : : tmplen, byte_data,
3125 : 0 : ULP_BITS_2_BYTE(tmplen));
3126 [ # # ]: 0 : if (rc) {
3127 : 0 : BNXT_TF_DBG(ERR, "Failed to write generic table\n");
3128 : 0 : return -EINVAL;
3129 : : }
3130 : :
3131 : : fdb_write = 1;
3132 : 0 : parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
3133 : 0 : break;
3134 : 0 : default:
3135 : 0 : BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
3136 : 0 : return -EINVAL;
3137 : : }
3138 : :
3139 : : /* Set the generic entry hit */
3140 : 0 : rc = ulp_regfile_write(parms->regfile,
3141 : : BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3142 [ # # ]: 0 : tfp_cpu_to_be_64(gen_tbl_miss));
3143 [ # # ]: 0 : if (rc) {
3144 : 0 : BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
3145 : : BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3146 : 0 : return -EIO;
3147 : : }
3148 : :
3149 : : /* add the entry to the flow database */
3150 [ # # ]: 0 : if (fdb_write) {
3151 : : memset(&fid_parms, 0, sizeof(fid_parms));
3152 : 0 : fid_parms.direction = tbl->direction;
3153 : 0 : fid_parms.resource_func = tbl->resource_func;
3154 : 0 : fid_parms.resource_sub_type = tbl->resource_sub_type;
3155 : 0 : fid_parms.resource_hndl = key_index;
3156 : 0 : fid_parms.critical_resource = tbl->critical_resource;
3157 : 0 : ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type);
3158 : :
3159 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
3160 [ # # ]: 0 : if (rc) {
3161 : 0 : BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
3162 : 0 : return rc;
3163 : : }
3164 : :
3165 : : /* Reset the in-flight RID when generic table is written and the
3166 : : * rid has been pushed into a handle (rid or fid). Once it has
3167 : : * been written, we have persistent accounting of the resources.
3168 : : */
3169 [ # # ]: 0 : if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_WRITE &&
3170 [ # # ]: 0 : (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE ||
3171 : : tbl->fdb_opcode == BNXT_ULP_FDB_OPC_PUSH_FID))
3172 : 0 : parms->rid = 0;
3173 : :
3174 : 0 : rc = ulp_mapper_gen_tbl_ref_cnt_process(parms, tbl,
3175 : : &gen_tbl_ent);
3176 : : }
3177 : :
3178 : : return rc;
3179 : : }
3180 : :
3181 : : static int32_t
3182 : 0 : ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
3183 : : struct bnxt_ulp_mapper_tbl_info *tbl)
3184 : : {
3185 : : int32_t rc = 0;
3186 : 0 : uint64_t val64 = 0;
3187 : : uint32_t rid;
3188 : :
3189 : : /* process the fdb opcode for alloc push */
3190 [ # # ]: 0 : if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
3191 : 0 : rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
3192 [ # # ]: 0 : if (rc) {
3193 : 0 : BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
3194 : 0 : return rc;
3195 : : }
3196 [ # # ]: 0 : } else if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_DELETE_RID_REGFILE) {
3197 : 0 : rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, &val64);
3198 [ # # ]: 0 : if (!rc) {
3199 : 0 : BNXT_TF_DBG(ERR, "Failed to get RID from regfile\n");
3200 : 0 : return rc;
3201 : : }
3202 [ # # ]: 0 : rid = (uint32_t)tfp_be_to_cpu_64(val64);
3203 : 0 : rc = ulp_mapper_resources_free(parms->ulp_ctx,
3204 : : BNXT_ULP_FDB_TYPE_RID,
3205 : : rid);
3206 : : }
3207 : :
3208 : : return rc;
3209 : : }
3210 : :
3211 : : static int32_t
3212 : 0 : ulp_mapper_vnic_tbl_process(struct bnxt_ulp_mapper_parms *parms,
3213 : : struct bnxt_ulp_mapper_tbl_info *tbl)
3214 : : {
3215 : : struct ulp_flow_db_res_params fid_parms;
3216 : 0 : uint16_t vnic_idx = 0, vnic_id = 0;
3217 : : int32_t rc = 0;
3218 : :
3219 [ # # # ]: 0 : switch (tbl->resource_sub_type) {
3220 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_RSS:
3221 [ # # ]: 0 : if (tbl->tbl_opcode != BNXT_ULP_VNIC_TBL_OPC_ALLOC_WR_REGFILE) {
3222 : 0 : BNXT_TF_DBG(ERR, "Invalid vnic table opcode\n");
3223 : 0 : return -EINVAL;
3224 : : }
3225 : 0 : rc = bnxt_pmd_rss_action_create(parms, &vnic_idx, &vnic_id);
3226 [ # # ]: 0 : if (rc) {
3227 : 0 : BNXT_TF_DBG(ERR, "Failed create rss action\n");
3228 : 0 : return rc;
3229 : : }
3230 : : break;
3231 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_QUEUE:
3232 [ # # ]: 0 : if (tbl->tbl_opcode != BNXT_ULP_VNIC_TBL_OPC_ALLOC_WR_REGFILE) {
3233 : 0 : BNXT_TF_DBG(ERR, "Invalid vnic table opcode\n");
3234 : 0 : return -EINVAL;
3235 : : }
3236 : 0 : rc = bnxt_pmd_queue_action_create(parms, &vnic_idx, &vnic_id);
3237 [ # # ]: 0 : if (rc) {
3238 : 0 : BNXT_TF_DBG(ERR, "Failed create queue action\n");
3239 : 0 : return rc;
3240 : : }
3241 : : break;
3242 : 0 : default:
3243 : 0 : BNXT_TF_DBG(ERR, "Invalid vnic table sub type\n");
3244 : 0 : return -EINVAL;
3245 : : }
3246 : :
3247 : : /* Link the created vnic to the flow in the flow db */
3248 : : memset(&fid_parms, 0, sizeof(fid_parms));
3249 : 0 : fid_parms.direction = tbl->direction;
3250 : 0 : fid_parms.resource_func = tbl->resource_func;
3251 : 0 : fid_parms.resource_type = tbl->resource_type;
3252 : 0 : fid_parms.resource_sub_type = tbl->resource_sub_type;
3253 : 0 : fid_parms.resource_hndl = vnic_idx;
3254 : 0 : fid_parms.critical_resource = tbl->critical_resource;
3255 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
3256 [ # # ]: 0 : if (rc) {
3257 : 0 : BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
3258 : : rc);
3259 : 0 : return rc;
3260 : : }
3261 : 0 : rc = ulp_regfile_write(parms->regfile, tbl->tbl_operand,
3262 [ # # ]: 0 : (uint64_t)tfp_cpu_to_be_64(vnic_id));
3263 [ # # ]: 0 : if (rc)
3264 : 0 : BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
3265 : : tbl->tbl_operand, rc);
3266 : :
3267 : : return rc;
3268 : : }
3269 : :
3270 : : /* Free the vnic resource */
3271 : : static int32_t
3272 : 0 : ulp_mapper_vnic_tbl_res_free(struct bnxt_ulp_context *ulp __rte_unused,
3273 : : struct tf *tfp,
3274 : : struct ulp_flow_db_res_params *res)
3275 : : {
3276 : 0 : uint16_t vnic_idx = res->resource_hndl;
3277 : :
3278 [ # # ]: 0 : if (res->resource_sub_type ==
3279 : : BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_QUEUE)
3280 : 0 : return bnxt_pmd_queue_action_delete(tfp, vnic_idx);
3281 : : else
3282 : 0 : return bnxt_pmd_rss_action_delete(tfp, vnic_idx);
3283 : : }
3284 : :
3285 : : static int32_t
3286 : 0 : ulp_mapper_global_res_free(struct bnxt_ulp_context *ulp __rte_unused,
3287 : : struct tf *tfp __rte_unused,
3288 : : struct ulp_flow_db_res_params *res)
3289 : : {
3290 : : uint16_t port_id = 0, dport = 0; /* Not needed for free */
3291 : : int32_t rc = 0;
3292 : : uint8_t ttype;
3293 : 0 : uint32_t handle = res->resource_hndl;
3294 : :
3295 [ # # # ]: 0 : switch (res->resource_sub_type) {
3296 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN:
3297 : : ttype = BNXT_GLOBAL_REGISTER_TUNNEL_VXLAN;
3298 : 0 : rc = bnxt_pmd_global_tunnel_set(port_id, ttype, dport,
3299 : : &handle);
3300 : 0 : break;
3301 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_ECPRI:
3302 : : ttype = BNXT_GLOBAL_REGISTER_TUNNEL_ECPRI;
3303 : 0 : rc = bnxt_pmd_global_tunnel_set(port_id, ttype, dport,
3304 : : &handle);
3305 : 0 : break;
3306 : 0 : default:
3307 : : rc = -EINVAL;
3308 : 0 : BNXT_TF_DBG(ERR, "Invalid ulp global resource type %d\n",
3309 : : res->resource_sub_type);
3310 : 0 : break;
3311 : : }
3312 : :
3313 : 0 : return rc;
3314 : : }
3315 : :
3316 : : static int32_t
3317 : 0 : ulp_mapper_global_register_tbl_process(struct bnxt_ulp_mapper_parms *parms,
3318 : : struct bnxt_ulp_mapper_tbl_info *tbl)
3319 : : {
3320 : 0 : struct ulp_flow_db_res_params fid_parms = { 0 };
3321 : : struct ulp_blob data;
3322 : 0 : uint16_t data_len = 0;
3323 : : uint8_t *tmp_data;
3324 : : uint16_t udp_port;
3325 : : uint32_t handle;
3326 : : int32_t rc = 0, write_reg = 0;
3327 : : uint8_t ttype;
3328 : :
3329 : : /* Initialize the blob data */
3330 [ # # ]: 0 : if (!ulp_blob_init(&data, tbl->result_bit_size,
3331 : : BNXT_ULP_BYTE_ORDER_BE)) {
3332 : 0 : BNXT_TF_DBG(ERR, "Failed initial ulp_global table blob\n");
3333 : 0 : return -EINVAL;
3334 : : }
3335 : :
3336 : : /* read the arguments from the result table */
3337 : 0 : rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
3338 : : "ULP Global Result");
3339 [ # # ]: 0 : if (rc) {
3340 : 0 : BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
3341 : 0 : return rc;
3342 : : }
3343 : :
3344 [ # # # ]: 0 : switch (tbl->tbl_opcode) {
3345 : 0 : case BNXT_ULP_GLOBAL_REGISTER_TBL_OPC_WR_REGFILE:
3346 : : write_reg = 1;
3347 : 0 : break;
3348 : : case BNXT_ULP_GLOBAL_REGISTER_TBL_OPC_NOT_USED:
3349 : : break;
3350 : 0 : default:
3351 : 0 : BNXT_TF_DBG(ERR, "Invalid global table opcode %d\n",
3352 : : tbl->tbl_opcode);
3353 : 0 : return -EINVAL;
3354 : : }
3355 : :
3356 [ # # # ]: 0 : switch (tbl->resource_sub_type) {
3357 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN:
3358 : 0 : tmp_data = ulp_blob_data_get(&data, &data_len);
3359 : 0 : udp_port = *((uint16_t *)tmp_data);
3360 [ # # ]: 0 : udp_port = tfp_be_to_cpu_16(udp_port);
3361 : : ttype = BNXT_GLOBAL_REGISTER_TUNNEL_VXLAN;
3362 : :
3363 : 0 : rc = bnxt_pmd_global_tunnel_set(parms->port_id, ttype,
3364 : : udp_port, &handle);
3365 [ # # ]: 0 : if (rc) {
3366 : 0 : BNXT_TF_DBG(ERR, "Unable to set VXLAN UDP port\n");
3367 : 0 : return rc;
3368 : : }
3369 : : break;
3370 : 0 : case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_ECPRI:
3371 : 0 : tmp_data = ulp_blob_data_get(&data, &data_len);
3372 : 0 : udp_port = *((uint16_t *)tmp_data);
3373 [ # # ]: 0 : udp_port = tfp_be_to_cpu_16(udp_port);
3374 : : ttype = BNXT_GLOBAL_REGISTER_TUNNEL_ECPRI;
3375 : :
3376 : 0 : rc = bnxt_pmd_global_tunnel_set(parms->port_id, ttype,
3377 : : udp_port, &handle);
3378 [ # # ]: 0 : if (rc) {
3379 : 0 : BNXT_TF_DBG(ERR, "Unable to set eCPRI UDP port\n");
3380 : 0 : return rc;
3381 : : }
3382 : : break;
3383 : 0 : default:
3384 : : rc = -EINVAL;
3385 : 0 : BNXT_TF_DBG(ERR, "Invalid ulp global resource type %d\n",
3386 : : tbl->resource_sub_type);
3387 : 0 : return rc;
3388 : : }
3389 : :
3390 : : /* Set the common pieces of fid parms */
3391 : 0 : fid_parms.direction = tbl->direction;
3392 : 0 : fid_parms.resource_func = tbl->resource_func;
3393 : 0 : fid_parms.resource_sub_type = tbl->resource_sub_type;
3394 : 0 : fid_parms.critical_resource = tbl->critical_resource;
3395 : 0 : fid_parms.resource_hndl = handle;
3396 : :
3397 : 0 : rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
3398 : :
3399 [ # # ]: 0 : if (rc)
3400 : : return rc;
3401 : :
3402 : : /* write to the regfile if opcode is set */
3403 [ # # ]: 0 : if (write_reg) {
3404 : 0 : rc = ulp_regfile_write(parms->regfile,
3405 : 0 : tbl->tbl_operand,
3406 [ # # ]: 0 : (uint64_t)tfp_cpu_to_be_64(handle));
3407 [ # # ]: 0 : if (rc)
3408 : 0 : BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
3409 : : tbl->tbl_operand);
3410 : : }
3411 : :
3412 : : return rc;
3413 : : }
3414 : :
3415 : : static int32_t
3416 : 0 : ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3417 : : struct bnxt_ulp_mapper_data *mapper_data)
3418 : : {
3419 : : struct bnxt_ulp_glb_resource_info *glb_res;
3420 : : uint32_t num_glb_res_ids, idx, dev_id;
3421 : : uint8_t app_id;
3422 : : int32_t rc = 0;
3423 : :
3424 : : glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
3425 : : if (!glb_res || !num_glb_res_ids) {
3426 : : BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3427 : : return -EINVAL;
3428 : : }
3429 : :
3430 : 0 : rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3431 [ # # ]: 0 : if (rc) {
3432 : 0 : BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
3433 : : rc);
3434 : 0 : return rc;
3435 : : }
3436 : :
3437 : 0 : rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3438 [ # # ]: 0 : if (rc) {
3439 : 0 : BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
3440 : : rc);
3441 : 0 : return rc;
3442 : : }
3443 : :
3444 : : /* Iterate the global resources and process each one */
3445 [ # # ]: 0 : for (idx = 0; idx < num_glb_res_ids; idx++) {
3446 [ # # ]: 0 : if (dev_id != glb_res[idx].device_id ||
3447 [ # # ]: 0 : glb_res[idx].app_id != app_id)
3448 : 0 : continue;
3449 [ # # # ]: 0 : switch (glb_res[idx].resource_func) {
3450 : 0 : case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3451 : 0 : rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
3452 : : mapper_data,
3453 : : &glb_res[idx],
3454 : : false);
3455 : 0 : break;
3456 : 0 : case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3457 : 0 : rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
3458 : : mapper_data,
3459 : : &glb_res[idx],
3460 : : false);
3461 : 0 : break;
3462 : 0 : default:
3463 : 0 : BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
3464 : : glb_res[idx].resource_func);
3465 : : rc = -EINVAL;
3466 : : break;
3467 : : }
3468 [ # # ]: 0 : if (rc)
3469 : 0 : return rc;
3470 : : }
3471 : : return rc;
3472 : : }
3473 : :
3474 : : static int32_t
3475 : 0 : ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3476 : : struct bnxt_ulp_mapper_data *mapper_data)
3477 : : {
3478 : : struct bnxt_ulp_glb_resource_info *glb_res;
3479 : : uint32_t num_glb_res_ids, idx, dev_id;
3480 : : uint8_t app_id;
3481 : : int32_t rc = 0;
3482 : :
3483 : 0 : glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_glb_res_ids);
3484 [ # # # # ]: 0 : if (!glb_res || !num_glb_res_ids) {
3485 : 0 : BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3486 : 0 : return -EINVAL;
3487 : : }
3488 : :
3489 : 0 : rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3490 [ # # ]: 0 : if (rc) {
3491 : 0 : BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
3492 : : rc);
3493 : 0 : return rc;
3494 : : }
3495 : :
3496 : 0 : rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3497 [ # # ]: 0 : if (rc) {
3498 : 0 : BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
3499 : : rc);
3500 : 0 : return rc;
3501 : : }
3502 : :
3503 : : /* Iterate the global resources and process each one */
3504 [ # # ]: 0 : for (idx = 0; idx < num_glb_res_ids; idx++) {
3505 [ # # ]: 0 : if (dev_id != glb_res[idx].device_id ||
3506 [ # # ]: 0 : glb_res[idx].app_id != app_id)
3507 : 0 : continue;
3508 [ # # # ]: 0 : switch (glb_res[idx].resource_func) {
3509 : 0 : case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3510 : 0 : rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
3511 : : mapper_data,
3512 : : &glb_res[idx],
3513 : : true);
3514 : 0 : break;
3515 : 0 : case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3516 : 0 : rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
3517 : : mapper_data,
3518 : : &glb_res[idx],
3519 : : true);
3520 : 0 : break;
3521 : 0 : default:
3522 : 0 : BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
3523 : : glb_res[idx].resource_func);
3524 : : rc = -EINVAL;
3525 : : break;
3526 : : }
3527 [ # # ]: 0 : if (rc)
3528 : 0 : return rc;
3529 : : }
3530 : : return rc;
3531 : : }
3532 : :
3533 : : /*
3534 : : * Common conditional opcode process routine that is used for both the template
3535 : : * rejection and table conditional execution.
3536 : : */
3537 : : static int32_t
3538 : 0 : ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
3539 : : enum bnxt_ulp_cond_opc opc,
3540 : : uint64_t operand,
3541 : : int32_t *res)
3542 : : {
3543 : 0 : enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
3544 : : uint32_t field_size = 0;
3545 : : int32_t rc = 0;
3546 : : uint8_t bit, tmp;
3547 : : uint64_t regval, result = 0;
3548 : :
3549 [ # # # # : 0 : switch (opc) {
# # # # #
# # # # #
# # # # ]
3550 : 0 : case BNXT_ULP_COND_OPC_CF_IS_SET:
3551 [ # # ]: 0 : if (operand < BNXT_ULP_CF_IDX_LAST) {
3552 [ # # ]: 0 : result = ULP_COMP_FLD_IDX_RD(parms, operand);
3553 : : } else {
3554 : 0 : BNXT_TF_DBG(ERR,
3555 : : "comp field out of bounds %" PRIu64 "\n",
3556 : : operand);
3557 : : rc = -EINVAL;
3558 : : }
3559 : : break;
3560 : 0 : case BNXT_ULP_COND_OPC_CF_NOT_SET:
3561 [ # # ]: 0 : if (operand < BNXT_ULP_CF_IDX_LAST) {
3562 [ # # ]: 0 : result = !ULP_COMP_FLD_IDX_RD(parms, operand);
3563 : : } else {
3564 : 0 : BNXT_TF_DBG(ERR,
3565 : : "comp field out of bounds %" PRIu64 "\n",
3566 : : operand);
3567 : : rc = -EINVAL;
3568 : : }
3569 : : break;
3570 : 0 : case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
3571 [ # # ]: 0 : if (operand < BNXT_ULP_ACT_BIT_LAST) {
3572 : 0 : result = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3573 : : operand);
3574 : : } else {
3575 : 0 : BNXT_TF_DBG(ERR,
3576 : : "action bit out of bounds %" PRIu64 "\n",
3577 : : operand);
3578 : : rc = -EINVAL;
3579 : : }
3580 : : break;
3581 : 0 : case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
3582 [ # # ]: 0 : if (operand < BNXT_ULP_ACT_BIT_LAST) {
3583 : 0 : result = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3584 : : operand);
3585 : : } else {
3586 : 0 : BNXT_TF_DBG(ERR,
3587 : : "action bit out of bounds %" PRIu64 "\n",
3588 : : operand);
3589 : : rc = -EINVAL;
3590 : : }
3591 : : break;
3592 : 0 : case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
3593 [ # # ]: 0 : if (operand < BNXT_ULP_HDR_BIT_LAST) {
3594 : 0 : result = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3595 : : operand);
3596 : : } else {
3597 : 0 : BNXT_TF_DBG(ERR,
3598 : : "header bit out of bounds %" PRIu64 "\n",
3599 : : operand);
3600 : : rc = -EINVAL;
3601 : : }
3602 : : break;
3603 : 0 : case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
3604 [ # # ]: 0 : if (operand < BNXT_ULP_HDR_BIT_LAST) {
3605 : 0 : result = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3606 : : operand);
3607 : : } else {
3608 : 0 : BNXT_TF_DBG(ERR,
3609 : : "header bit out of bounds %" PRIu64 "\n",
3610 : : operand);
3611 : : rc = -EINVAL;
3612 : : }
3613 : : break;
3614 : 0 : case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
3615 : 0 : rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3616 [ # # ]: 0 : if (rc) {
3617 : 0 : BNXT_TF_DBG(ERR,
3618 : : "invalid ulp_glb_field_tbl idx %" PRIu64 "\n",
3619 : : operand);
3620 : 0 : return -EINVAL;
3621 : : }
3622 : 0 : result = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3623 : 0 : break;
3624 : 0 : case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
3625 : 0 : rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3626 [ # # ]: 0 : if (rc) {
3627 : 0 : BNXT_TF_DBG(ERR,
3628 : : "invalid ulp_glb_field_tbl idx %" PRIu64 "\n",
3629 : : operand);
3630 : 0 : return -EINVAL;
3631 : : }
3632 : 0 : result = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3633 : 0 : break;
3634 : 0 : case BNXT_ULP_COND_OPC_RF_IS_SET:
3635 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
3636 : 0 : BNXT_TF_DBG(ERR,
3637 : : "regfile[%" PRIu64 "] read oob\n",
3638 : : operand);
3639 : 0 : return -EINVAL;
3640 : : }
3641 : 0 : result = regval != 0;
3642 : 0 : break;
3643 : 0 : case BNXT_ULP_COND_OPC_RF_NOT_SET:
3644 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
3645 : 0 : BNXT_TF_DBG(ERR,
3646 : : "regfile[%" PRIu64 "] read oob\n", operand);
3647 : 0 : return -EINVAL;
3648 : : }
3649 : 0 : result = regval == 0;
3650 : 0 : break;
3651 : 0 : case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
3652 : 0 : result = parms->flow_pattern_id == operand;
3653 : 0 : break;
3654 : 0 : case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
3655 : 0 : result = parms->act_pattern_id == operand;
3656 : 0 : break;
3657 : 0 : case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
3658 [ # # ]: 0 : if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3659 : 0 : BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3660 : 0 : return -EINVAL;
3661 : : }
3662 : 0 : result = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
3663 : 0 : break;
3664 : 0 : case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
3665 [ # # ]: 0 : if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3666 : 0 : BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3667 : 0 : return -EINVAL;
3668 : : }
3669 : 0 : result = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
3670 : 0 : break;
3671 : 0 : case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET:
3672 [ # # ]: 0 : if (operand < BNXT_ULP_HDR_BIT_LAST) {
3673 : 0 : result = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3674 : : operand);
3675 : : } else {
3676 : 0 : BNXT_TF_DBG(ERR,
3677 : : "header bit out of bounds %" PRIu64 "\n",
3678 : : operand);
3679 : : rc = -EINVAL;
3680 : : }
3681 : : break;
3682 : 0 : case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET:
3683 [ # # ]: 0 : if (operand < BNXT_ULP_HDR_BIT_LAST) {
3684 : 0 : result = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3685 : : operand);
3686 : : } else {
3687 : 0 : BNXT_TF_DBG(ERR,
3688 : : "header bit out of bounds %" PRIu64 "\n",
3689 : : operand);
3690 : : rc = -EINVAL;
3691 : : }
3692 : : break;
3693 : 0 : case BNXT_ULP_COND_OPC_ACT_PROP_IS_SET:
3694 : : case BNXT_ULP_COND_OPC_ACT_PROP_NOT_SET:
3695 : : /* only supporting 1-byte action properties for now */
3696 [ # # ]: 0 : if (operand >= BNXT_ULP_ACT_PROP_IDX_LAST) {
3697 : 0 : BNXT_TF_DBG(ERR,
3698 : : "act_prop[%" PRIu64 "] oob\n", operand);
3699 : 0 : return -EINVAL;
3700 : : }
3701 : 0 : field_size = ulp_mapper_act_prop_size_get(operand);
3702 [ # # ]: 0 : if (sizeof(tmp) != field_size) {
3703 : 0 : BNXT_TF_DBG(ERR,
3704 : : "act_prop[%" PRIu64 "] field mismatch %u\n",
3705 : : operand, field_size);
3706 : 0 : return -EINVAL;
3707 : : }
3708 : 0 : tmp = parms->act_prop->act_details[operand];
3709 [ # # ]: 0 : if (opc == BNXT_ULP_COND_OPC_ACT_PROP_IS_SET)
3710 : 0 : result = (int32_t)(tmp);
3711 : : else
3712 : 0 : result = (int32_t)(!tmp);
3713 : : break;
3714 : 0 : default:
3715 : 0 : BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
3716 : : rc = -EINVAL;
3717 : 0 : break;
3718 : : }
3719 : :
3720 : 0 : *res = !!result;
3721 : 0 : return (rc);
3722 : : }
3723 : :
3724 : : static int32_t
3725 : 0 : ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms,
3726 : : enum tf_dir dir,
3727 : : enum bnxt_ulp_func_src func_src,
3728 : : uint16_t func_opr,
3729 : : uint64_t *result)
3730 : : {
3731 : : uint64_t regval;
3732 : : bool shared;
3733 : :
3734 : 0 : *result = false;
3735 [ # # # # : 0 : switch (func_src) {
# ]
3736 : 0 : case BNXT_ULP_FUNC_SRC_COMP_FIELD:
3737 [ # # ]: 0 : if (func_opr >= BNXT_ULP_CF_IDX_LAST) {
3738 : 0 : BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr);
3739 : 0 : return -EINVAL;
3740 : : }
3741 [ # # ]: 0 : *result = ULP_COMP_FLD_IDX_RD(parms, func_opr);
3742 : 0 : break;
3743 : 0 : case BNXT_ULP_FUNC_SRC_REGFILE:
3744 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile, func_opr, ®val)) {
3745 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr);
3746 : 0 : return -EINVAL;
3747 : : }
3748 [ # # ]: 0 : *result = tfp_be_to_cpu_64(regval);
3749 : 0 : break;
3750 : 0 : case BNXT_ULP_FUNC_SRC_GLB_REGFILE:
3751 [ # # ]: 0 : if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3752 : : func_opr, ®val, &shared)) {
3753 : 0 : BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3754 : : func_opr);
3755 : 0 : return -EINVAL;
3756 : : }
3757 [ # # ]: 0 : *result = tfp_be_to_cpu_64(regval);
3758 : 0 : break;
3759 : 0 : case BNXT_ULP_FUNC_SRC_CONST:
3760 : 0 : *result = func_opr;
3761 : 0 : break;
3762 : 0 : default:
3763 : 0 : BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src);
3764 : 0 : return -EINVAL;
3765 : : }
3766 : : return 0;
3767 : : }
3768 : :
3769 : : static int32_t
3770 : 0 : ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms,
3771 : : struct bnxt_ulp_mapper_tbl_info *tbl)
3772 : : {
3773 : : struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info;
3774 : 0 : uint64_t res = 0, res1 = 0, res2 = 0;
3775 : : int32_t rc = 0;
3776 : : uint32_t process_src1 = 0, process_src2 = 0;
3777 : :
3778 : : /* determine which functional operands to compute */
3779 [ # # # # ]: 0 : switch (func_info->func_opc) {
3780 : : case BNXT_ULP_FUNC_OPC_NOP:
3781 : : return rc;
3782 : : case BNXT_ULP_FUNC_OPC_EQ:
3783 : : case BNXT_ULP_FUNC_OPC_NE:
3784 : : case BNXT_ULP_FUNC_OPC_GE:
3785 : : case BNXT_ULP_FUNC_OPC_GT:
3786 : : case BNXT_ULP_FUNC_OPC_LE:
3787 : : case BNXT_ULP_FUNC_OPC_LT:
3788 : : process_src1 = 1;
3789 : : process_src2 = 1;
3790 : : break;
3791 : : case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3792 : : process_src1 = 1;
3793 : : break;
3794 : : default:
3795 : : break;
3796 : : }
3797 : :
3798 : : if (process_src1) {
3799 : 0 : rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3800 : : func_info->func_src1,
3801 : 0 : func_info->func_opr1, &res1);
3802 [ # # ]: 0 : if (rc)
3803 : : return rc;
3804 : : }
3805 : :
3806 [ # # ]: 0 : if (process_src2) {
3807 : 0 : rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3808 : : func_info->func_src2,
3809 : 0 : func_info->func_opr2, &res2);
3810 [ # # ]: 0 : if (rc)
3811 : : return rc;
3812 : : }
3813 : :
3814 : : /* perform the functional opcode operations */
3815 [ # # # # : 0 : switch (func_info->func_opc) {
# # # # #
# ]
3816 : 0 : case BNXT_ULP_FUNC_OPC_EQ:
3817 [ # # ]: 0 : if (res1 == res2)
3818 : 0 : res = 1;
3819 : : break;
3820 : 0 : case BNXT_ULP_FUNC_OPC_NE:
3821 [ # # ]: 0 : if (res1 != res2)
3822 : 0 : res = 1;
3823 : : break;
3824 : 0 : case BNXT_ULP_FUNC_OPC_GE:
3825 [ # # ]: 0 : if (res1 >= res2)
3826 : 0 : res = 1;
3827 : : break;
3828 : 0 : case BNXT_ULP_FUNC_OPC_GT:
3829 [ # # ]: 0 : if (res1 > res2)
3830 : 0 : res = 1;
3831 : : break;
3832 : 0 : case BNXT_ULP_FUNC_OPC_LE:
3833 [ # # ]: 0 : if (res1 <= res2)
3834 : 0 : res = 1;
3835 : : break;
3836 : 0 : case BNXT_ULP_FUNC_OPC_LT:
3837 [ # # ]: 0 : if (res1 < res2)
3838 : 0 : res = 1;
3839 : : break;
3840 : 0 : case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3841 : 0 : res = res1;
3842 : 0 : break;
3843 : 0 : case BNXT_ULP_FUNC_OPC_RSS_CONFIG:
3844 : : /* apply the rss config using pmd method */
3845 : 0 : return bnxt_rss_config_action_apply(parms);
3846 : 0 : case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR:
3847 : 0 : rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res);
3848 [ # # ]: 0 : if (rc)
3849 : : return -EINVAL;
3850 [ # # ]: 0 : res = tfp_be_to_cpu_64(res);
3851 : 0 : break;
3852 : 0 : default:
3853 : 0 : BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc);
3854 : 0 : return -EINVAL;
3855 : : }
3856 [ # # ]: 0 : if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr,
3857 [ # # ]: 0 : tfp_cpu_to_be_64(res))) {
3858 : 0 : BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n",
3859 : : func_info->func_dst_opr);
3860 : 0 : return -EINVAL;
3861 : : }
3862 : :
3863 : : return rc;
3864 : : }
3865 : :
3866 : : /*
3867 : : * Processes a list of conditions and returns both a status and result of the
3868 : : * list. The status must be checked prior to verifying the result.
3869 : : *
3870 : : * returns 0 for success, negative on failure
3871 : : * returns res = 1 for true, res = 0 for false.
3872 : : */
3873 : : static int32_t
3874 : 0 : ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3875 : : enum bnxt_ulp_cond_list_opc list_opc,
3876 : : struct bnxt_ulp_mapper_cond_info *list,
3877 : : uint32_t num,
3878 : : int32_t *res)
3879 : : {
3880 : : uint32_t i;
3881 : 0 : int32_t rc = 0, trc = 0;
3882 : :
3883 [ # # # # : 0 : switch (list_opc) {
# ]
3884 : 0 : case BNXT_ULP_COND_LIST_OPC_AND:
3885 : : /* AND Defaults to true. */
3886 : 0 : *res = 1;
3887 : 0 : break;
3888 : 0 : case BNXT_ULP_COND_LIST_OPC_OR:
3889 : : /* OR Defaults to false. */
3890 : 0 : *res = 0;
3891 : 0 : break;
3892 : 0 : case BNXT_ULP_COND_LIST_OPC_TRUE:
3893 : 0 : *res = 1;
3894 : 0 : return rc;
3895 : 0 : case BNXT_ULP_COND_LIST_OPC_FALSE:
3896 : 0 : *res = 0;
3897 : 0 : return rc;
3898 : 0 : default:
3899 : 0 : BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3900 : : list_opc);
3901 : 0 : *res = 0;
3902 : 0 : return -EINVAL;
3903 : : }
3904 : :
3905 [ # # ]: 0 : for (i = 0; i < num; i++) {
3906 : 0 : rc = ulp_mapper_cond_opc_process(parms,
3907 : : list[i].cond_opcode,
3908 : 0 : list[i].cond_operand,
3909 : : &trc);
3910 [ # # ]: 0 : if (rc)
3911 : 0 : return rc;
3912 : :
3913 [ # # ]: 0 : if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3914 : : /* early return if result is ever zero */
3915 [ # # ]: 0 : if (!trc) {
3916 : 0 : *res = trc;
3917 : 0 : return rc;
3918 : : }
3919 : : } else {
3920 : : /* early return if result is ever non-zero */
3921 [ # # ]: 0 : if (trc) {
3922 : 0 : *res = trc;
3923 : 0 : return rc;
3924 : : }
3925 : : }
3926 : : }
3927 : :
3928 : : return rc;
3929 : : }
3930 : :
3931 : : /*
3932 : : * Processes conflict resolution and returns both a status and result.
3933 : : * The status must be checked prior to verifying the result.
3934 : : *
3935 : : * returns 0 for success, negative on failure
3936 : : * returns res = 1 for true, res = 0 for false.
3937 : : */
3938 : : static int32_t
3939 : 0 : ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3940 : : struct bnxt_ulp_mapper_tbl_info *tbl,
3941 : : int32_t *res)
3942 : : {
3943 : : int32_t rc = 0;
3944 : : uint64_t regval;
3945 : : uint64_t comp_sig;
3946 : :
3947 : 0 : *res = 0;
3948 [ # # # ]: 0 : switch (tbl->accept_opcode) {
3949 : 0 : case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3950 : 0 : *res = 1;
3951 : 0 : break;
3952 : 0 : case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3953 : : /* perform the signature validation*/
3954 [ # # ]: 0 : if (tbl->resource_func ==
3955 : : BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3956 : : /* Perform the check that generic table is hit or not */
3957 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
3958 : : BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3959 : : ®val)) {
3960 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3961 : : BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3962 : 0 : return -EINVAL;
3963 : : }
3964 [ # # ]: 0 : if (regval) {
3965 : : /* not a hit so no need to check flow sign*/
3966 : 0 : *res = 1;
3967 : 0 : return rc;
3968 : : }
3969 : : }
3970 : : /* compare the new flow signature against stored one */
3971 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile,
3972 : : BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3973 : : ®val)) {
3974 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3975 : : BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3976 : 0 : return -EINVAL;
3977 : : }
3978 [ # # ]: 0 : comp_sig = ULP_COMP_FLD_IDX_RD(parms,
3979 : : BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3980 [ # # ]: 0 : regval = tfp_be_to_cpu_64(regval);
3981 [ # # ]: 0 : if (comp_sig == regval)
3982 : 0 : *res = 1;
3983 : : else
3984 : 0 : BNXT_TF_DBG(ERR, "failed signature match 0x%016"
3985 : : PRIX64 ":%x\n", comp_sig, (uint32_t)regval);
3986 : : break;
3987 : 0 : default:
3988 : 0 : BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3989 : : tbl->accept_opcode);
3990 : 0 : return -EINVAL;
3991 : : }
3992 : : return rc;
3993 : : }
3994 : :
3995 : : static int32_t
3996 : 0 : ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3997 : : {
3998 : : struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3999 : : enum bnxt_ulp_cond_list_opc cond_opc;
4000 : : struct bnxt_ulp_mapper_tbl_info *tbls;
4001 : : struct bnxt_ulp_mapper_tbl_info *tbl;
4002 : : uint32_t num_tbls, tbl_idx, num_cond_tbls;
4003 : 0 : int32_t rc = -EINVAL, cond_rc = 0;
4004 : : int32_t cond_goto = 1;
4005 : :
4006 : : cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
4007 : : &num_cond_tbls,
4008 : : &cond_opc);
4009 : : /*
4010 : : * Process the reject list if exists, otherwise assume that the
4011 : : * template is allowed.
4012 : : */
4013 [ # # # # ]: 0 : if (cond_tbls && num_cond_tbls) {
4014 : 0 : rc = ulp_mapper_cond_opc_list_process(parms,
4015 : : cond_opc,
4016 : : cond_tbls,
4017 : : num_cond_tbls,
4018 : : &cond_rc);
4019 [ # # ]: 0 : if (rc)
4020 : : return rc;
4021 : :
4022 : : /* Reject the template if True */
4023 [ # # ]: 0 : if (cond_rc) {
4024 [ # # # ]: 0 : BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
4025 : : ulp_mapper_tmpl_name_str(parms->tmpl_type),
4026 : : tid);
4027 : 0 : return -EINVAL;
4028 : : }
4029 : : }
4030 : :
4031 : : tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
4032 [ # # # # ]: 0 : if (!tbls || !num_tbls) {
4033 [ # # # ]: 0 : BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
4034 : : ulp_mapper_tmpl_name_str(parms->tmpl_type),
4035 : : parms->dev_id, tid);
4036 : 0 : return -EINVAL;
4037 : : }
4038 : :
4039 [ # # # # ]: 0 : for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
4040 : 0 : tbl = &tbls[tbl_idx];
4041 : 0 : cond_goto = tbl->execute_info.cond_true_goto;
4042 : : /* Process the conditional func code opcodes */
4043 [ # # ]: 0 : if (ulp_mapper_func_info_process(parms, tbl)) {
4044 : 0 : BNXT_TF_DBG(ERR, "Failed to process cond update\n");
4045 : : rc = -EINVAL;
4046 : 0 : goto error;
4047 : : }
4048 : :
4049 : : cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
4050 : : &num_cond_tbls,
4051 : : &cond_opc);
4052 : 0 : rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
4053 : : cond_tbls, num_cond_tbls,
4054 : : &cond_rc);
4055 [ # # ]: 0 : if (rc) {
4056 : 0 : BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n",
4057 : : rc);
4058 : 0 : goto error;
4059 : : }
4060 : : /* Skip the table if False */
4061 [ # # ]: 0 : if (!cond_rc) {
4062 : 0 : cond_goto = tbl->execute_info.cond_false_goto;
4063 : 0 : goto next_iteration;
4064 : : }
4065 : :
4066 [ # # # # : 0 : switch (tbl->resource_func) {
# # # # #
# ]
4067 : 0 : case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
4068 : 0 : rc = ulp_mapper_tcam_tbl_process(parms, tbl);
4069 : 0 : break;
4070 : 0 : case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
4071 : 0 : rc = ulp_mapper_em_tbl_process(parms, tbl);
4072 : 0 : break;
4073 : 0 : case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
4074 : 0 : rc = ulp_mapper_index_tbl_process(parms, tbl);
4075 : 0 : break;
4076 : 0 : case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
4077 : 0 : rc = ulp_mapper_if_tbl_process(parms, tbl);
4078 : 0 : break;
4079 : 0 : case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
4080 : 0 : rc = ulp_mapper_gen_tbl_process(parms, tbl);
4081 : 0 : break;
4082 : 0 : case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
4083 : 0 : rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
4084 : 0 : break;
4085 : 0 : case BNXT_ULP_RESOURCE_FUNC_VNIC_TABLE:
4086 : 0 : rc = ulp_mapper_vnic_tbl_process(parms, tbl);
4087 : 0 : break;
4088 : 0 : case BNXT_ULP_RESOURCE_FUNC_GLOBAL_REGISTER_TABLE:
4089 : 0 : rc = ulp_mapper_global_register_tbl_process(parms, tbl);
4090 : 0 : break;
4091 : : case BNXT_ULP_RESOURCE_FUNC_INVALID:
4092 : : rc = 0;
4093 : : break;
4094 : 0 : default:
4095 : 0 : BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
4096 : : tbl->resource_func);
4097 : : rc = -EINVAL;
4098 : 0 : goto error;
4099 : : }
4100 : :
4101 [ # # ]: 0 : if (rc) {
4102 : 0 : BNXT_TF_DBG(ERR, "Resource type %d failed\n",
4103 : : tbl->resource_func);
4104 : 0 : goto error;
4105 : : }
4106 : :
4107 : : /* perform the post table process */
4108 : 0 : rc = ulp_mapper_conflict_resolution_process(parms, tbl,
4109 : : &cond_rc);
4110 [ # # # # ]: 0 : if (rc || !cond_rc) {
4111 : 0 : BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
4112 : : rc = -EINVAL;
4113 : 0 : goto error;
4114 : : }
4115 : 0 : next_iteration:
4116 [ # # ]: 0 : if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
4117 : 0 : BNXT_TF_DBG(ERR, "reject the flow\n");
4118 : : rc = -EINVAL;
4119 : 0 : goto error;
4120 [ # # ]: 0 : } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
4121 : : uint32_t rf_idx;
4122 : : uint64_t regval;
4123 : :
4124 : : /* least significant 16 bits from reg_file index */
4125 : 0 : rf_idx = (uint32_t)(cond_goto & 0xFFFF);
4126 [ # # ]: 0 : if (!ulp_regfile_read(parms->regfile, rf_idx,
4127 : : ®val)) {
4128 : 0 : BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
4129 : : rf_idx);
4130 : : rc = -EINVAL;
4131 : 0 : goto error;
4132 : : }
4133 : 0 : cond_goto = (int32_t)regval;
4134 : : }
4135 : :
4136 [ # # # # ]: 0 : if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
4137 : 0 : BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
4138 : : cond_goto);
4139 : 0 : goto error;
4140 : : }
4141 : 0 : tbl_idx += cond_goto;
4142 : : }
4143 : :
4144 : : return rc;
4145 : 0 : error:
4146 [ # # # ]: 0 : BNXT_TF_DBG(ERR, "%s tables failed operation for %d:%d\n",
4147 : : ulp_mapper_tmpl_name_str(parms->tmpl_type),
4148 : : parms->dev_id, tid);
4149 : 0 : return rc;
4150 : : }
4151 : :
4152 : : static int32_t
4153 : 0 : ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
4154 : : uint32_t fid,
4155 : : struct ulp_flow_db_res_params *res)
4156 : : {
4157 : : struct tf *tfp;
4158 : : int32_t rc = 0;
4159 : :
4160 [ # # ]: 0 : if (!res || !ulp) {
4161 : 0 : BNXT_TF_DBG(ERR, "Unable to free resource\n ");
4162 : 0 : return -EINVAL;
4163 : : }
4164 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(ulp, ulp_flow_db_shared_session_get(res));
4165 [ # # ]: 0 : if (!tfp) {
4166 : 0 : BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
4167 : 0 : return -EINVAL;
4168 : : }
4169 : :
4170 [ # # # # : 0 : switch (res->resource_func) {
# # # # #
# # ]
4171 : 0 : case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
4172 : 0 : rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
4173 : 0 : break;
4174 : 0 : case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
4175 : 0 : rc = ulp_mapper_em_entry_free(ulp, tfp, res);
4176 : 0 : break;
4177 : 0 : case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
4178 : 0 : rc = ulp_mapper_index_entry_free(ulp, tfp, res);
4179 : 0 : break;
4180 : : case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
4181 : : rc = ulp_mapper_ident_free(ulp, tfp, res);
4182 : 0 : break;
4183 : : case BNXT_ULP_RESOURCE_FUNC_HW_FID:
4184 : : rc = ulp_mapper_mark_free(ulp, res);
4185 : 0 : break;
4186 : 0 : case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
4187 : 0 : rc = ulp_mapper_parent_flow_free(ulp, fid, res);
4188 : 0 : break;
4189 : 0 : case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
4190 : 0 : rc = ulp_mapper_child_flow_free(ulp, fid, res);
4191 : 0 : break;
4192 : 0 : case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
4193 : 0 : rc = ulp_mapper_gen_tbl_res_free(ulp, fid, res);
4194 : 0 : break;
4195 : 0 : case BNXT_ULP_RESOURCE_FUNC_VNIC_TABLE:
4196 : 0 : rc = ulp_mapper_vnic_tbl_res_free(ulp, tfp, res);
4197 : 0 : break;
4198 : 0 : case BNXT_ULP_RESOURCE_FUNC_GLOBAL_REGISTER_TABLE:
4199 : 0 : rc = ulp_mapper_global_res_free(ulp, tfp, res);
4200 : 0 : break;
4201 : : default:
4202 : : break;
4203 : : }
4204 : :
4205 : : return rc;
4206 : : }
4207 : :
4208 : : int32_t
4209 : 0 : ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
4210 : : enum bnxt_ulp_fdb_type flow_type,
4211 : : uint32_t fid)
4212 : : {
4213 : 0 : struct ulp_flow_db_res_params res_parms = { 0 };
4214 : : int32_t rc, trc;
4215 : :
4216 [ # # ]: 0 : if (!ulp_ctx) {
4217 : 0 : BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
4218 : 0 : return -EINVAL;
4219 : : }
4220 : :
4221 : : /*
4222 : : * Set the critical resource on the first resource del, then iterate
4223 : : * while status is good
4224 : : */
4225 : 0 : res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
4226 : :
4227 : 0 : rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
4228 : :
4229 [ # # ]: 0 : if (rc) {
4230 : : /*
4231 : : * This is unexpected on the first call to resource del.
4232 : : * It likely means that the flow did not exist in the flow db.
4233 : : */
4234 : 0 : BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
4235 : : flow_type, fid, rc);
4236 : 0 : return rc;
4237 : : }
4238 : :
4239 [ # # ]: 0 : while (!rc) {
4240 : 0 : trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
4241 [ # # ]: 0 : if (trc)
4242 : : /*
4243 : : * On fail, we still need to attempt to free the
4244 : : * remaining resources. Don't return
4245 : : */
4246 : 0 : BNXT_TF_DBG(ERR,
4247 : : "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
4248 : : "] failed rc=%d.\n",
4249 : : flow_type, fid, res_parms.resource_func,
4250 : : res_parms.resource_hndl, trc);
4251 : :
4252 : : /* All subsequent call require the non-critical_resource */
4253 : 0 : res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
4254 : :
4255 : 0 : rc = ulp_flow_db_resource_del(ulp_ctx,
4256 : : flow_type,
4257 : : fid,
4258 : : &res_parms);
4259 : : }
4260 : :
4261 : : /* Free the Flow ID since we've removed all resources */
4262 : 0 : rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
4263 : :
4264 : 0 : return rc;
4265 : : }
4266 : :
4267 : : static void
4268 : 0 : ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
4269 : : struct bnxt_ulp_mapper_data *mapper_data)
4270 : : {
4271 : : struct bnxt_ulp_mapper_glb_resource_entry *ent;
4272 : : struct ulp_flow_db_res_params res;
4273 : : uint32_t dir, idx;
4274 : :
4275 : : /* Iterate the global resources and process each one */
4276 [ # # ]: 0 : for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
4277 [ # # ]: 0 : for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) {
4278 : : ent = &mapper_data->glb_res_tbl[dir][idx];
4279 [ # # ]: 0 : if (ent->resource_func ==
4280 : 0 : BNXT_ULP_RESOURCE_FUNC_INVALID ||
4281 [ # # ]: 0 : ent->shared)
4282 : 0 : continue;
4283 : : memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
4284 : 0 : res.resource_func = ent->resource_func;
4285 : 0 : res.direction = dir;
4286 : 0 : res.resource_type = ent->resource_type;
4287 : : /*convert it from BE to cpu */
4288 : 0 : res.resource_hndl =
4289 [ # # ]: 0 : tfp_be_to_cpu_64(ent->resource_hndl);
4290 : 0 : ulp_mapper_resource_free(ulp_ctx, 0, &res);
4291 : : }
4292 : : }
4293 : 0 : }
4294 : :
4295 : : int32_t
4296 : 0 : ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
4297 : : enum bnxt_ulp_fdb_type flow_type,
4298 : : uint32_t fid)
4299 : : {
4300 : : int32_t rc;
4301 : :
4302 [ # # ]: 0 : if (!ulp_ctx) {
4303 : 0 : BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
4304 : 0 : return -EINVAL;
4305 : : }
4306 : :
4307 : 0 : rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
4308 : 0 : return rc;
4309 : : }
4310 : :
4311 : : /* Function to handle the mapping of the Flow to be compatible
4312 : : * with the underlying hardware.
4313 : : */
4314 : : int32_t
4315 : 0 : ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
4316 : : struct bnxt_ulp_mapper_create_parms *cparms)
4317 : : {
4318 : : struct bnxt_ulp_mapper_parms parms;
4319 : : struct ulp_regfile regfile;
4320 : : int32_t rc = 0, trc;
4321 : :
4322 [ # # ]: 0 : if (!ulp_ctx || !cparms)
4323 : : return -EINVAL;
4324 : :
4325 : : /* Initialize the parms structure */
4326 : : memset(&parms, 0, sizeof(parms));
4327 : 0 : parms.act_prop = cparms->act_prop;
4328 : 0 : parms.act_bitmap = cparms->act;
4329 : 0 : parms.hdr_bitmap = cparms->hdr_bitmap;
4330 : 0 : parms.enc_hdr_bitmap = cparms->enc_hdr_bitmap;
4331 : 0 : parms.regfile = ®file;
4332 : 0 : parms.hdr_field = cparms->hdr_field;
4333 : 0 : parms.enc_field = cparms->enc_field;
4334 : 0 : parms.fld_bitmap = cparms->fld_bitmap;
4335 : 0 : parms.comp_fld = cparms->comp_fld;
4336 : 0 : parms.ulp_ctx = ulp_ctx;
4337 : 0 : parms.act_tid = cparms->act_tid;
4338 : 0 : parms.class_tid = cparms->class_tid;
4339 : 0 : parms.flow_type = cparms->flow_type;
4340 : 0 : parms.parent_flow = cparms->parent_flow;
4341 : 0 : parms.child_flow = cparms->child_flow;
4342 : 0 : parms.fid = cparms->flow_id;
4343 : 0 : parms.tun_idx = cparms->tun_idx;
4344 : 0 : parms.app_priority = cparms->app_priority;
4345 : 0 : parms.flow_pattern_id = cparms->flow_pattern_id;
4346 : 0 : parms.act_pattern_id = cparms->act_pattern_id;
4347 : 0 : parms.app_id = cparms->app_id;
4348 : 0 : parms.port_id = cparms->port_id;
4349 : :
4350 : : /* Get the device id from the ulp context */
4351 [ # # ]: 0 : if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
4352 : 0 : BNXT_TF_DBG(ERR, "Invalid ulp context\n");
4353 : 0 : return -EINVAL;
4354 : : }
4355 : :
4356 : : /* Get the device params, it will be used in later processing */
4357 : 0 : parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
4358 [ # # ]: 0 : if (!parms.device_params) {
4359 : 0 : BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
4360 : : parms.dev_id);
4361 : 0 : return -EINVAL;
4362 : : }
4363 : :
4364 : : /*
4365 : : * Get the mapper data for dynamic mapper data such as default
4366 : : * ids.
4367 : : */
4368 : 0 : parms.mapper_data = (struct bnxt_ulp_mapper_data *)
4369 : 0 : bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4370 [ # # ]: 0 : if (!parms.mapper_data) {
4371 : 0 : BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
4372 : 0 : return -EINVAL;
4373 : : }
4374 : :
4375 : : /* initialize the registry file for further processing */
4376 [ # # ]: 0 : if (!ulp_regfile_init(parms.regfile)) {
4377 : 0 : BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
4378 : 0 : return -EINVAL;
4379 : : }
4380 : :
4381 : : /* Process the action template list from the selected action table*/
4382 [ # # ]: 0 : if (parms.act_tid) {
4383 : 0 : parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
4384 : : /* Process the action template tables */
4385 : 0 : rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
4386 [ # # ]: 0 : if (rc)
4387 : 0 : goto flow_error;
4388 : 0 : cparms->shared_hndl = parms.shared_hndl;
4389 : : }
4390 : :
4391 [ # # ]: 0 : if (parms.class_tid) {
4392 : 0 : parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
4393 : :
4394 : : /* Process the class template tables.*/
4395 : 0 : rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
4396 [ # # ]: 0 : if (rc)
4397 : 0 : goto flow_error;
4398 : : }
4399 : :
4400 : : /* setup the parent-child details */
4401 [ # # ]: 0 : if (parms.parent_flow) {
4402 : : /* create a parent flow details */
4403 : 0 : rc = ulp_flow_db_parent_flow_create(&parms);
4404 [ # # ]: 0 : if (rc)
4405 : 0 : goto flow_error;
4406 [ # # ]: 0 : } else if (parms.child_flow) {
4407 : : /* create a child flow details */
4408 : 0 : rc = ulp_flow_db_child_flow_create(&parms);
4409 [ # # ]: 0 : if (rc)
4410 : 0 : goto flow_error;
4411 : : }
4412 : :
4413 : : return rc;
4414 : :
4415 : 0 : flow_error:
4416 [ # # ]: 0 : if (parms.rid) {
4417 : : /* An RID was in-flight but not pushed, free the resources */
4418 : 0 : trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID,
4419 : : parms.rid);
4420 [ # # ]: 0 : if (trc)
4421 : 0 : BNXT_TF_DBG(ERR,
4422 : : "Failed to free resources rid=0x%08x rc=%d\n",
4423 : : parms.rid, trc);
4424 : 0 : parms.rid = 0;
4425 : : }
4426 : :
4427 : : /* Free all resources that were allocated during flow creation */
4428 [ # # ]: 0 : if (parms.fid) {
4429 : 0 : trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
4430 : : parms.fid);
4431 [ # # ]: 0 : if (trc)
4432 : 0 : BNXT_TF_DBG(ERR,
4433 : : "Failed to free resources fid=0x%08x rc=%d\n",
4434 : : parms.fid, trc);
4435 : : }
4436 : :
4437 : : return rc;
4438 : : }
4439 : :
4440 : : int32_t
4441 : 0 : ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
4442 : : {
4443 : : struct bnxt_ulp_mapper_data *data;
4444 : : struct tf *tfp;
4445 : : int32_t rc;
4446 : :
4447 [ # # ]: 0 : if (!ulp_ctx)
4448 : : return -EINVAL;
4449 : :
4450 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT);
4451 [ # # ]: 0 : if (!tfp)
4452 : : return -EINVAL;
4453 : :
4454 : 0 : data = rte_zmalloc("ulp_mapper_data",
4455 : : sizeof(struct bnxt_ulp_mapper_data), 0);
4456 [ # # ]: 0 : if (!data) {
4457 : 0 : BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
4458 : 0 : return -ENOMEM;
4459 : : }
4460 : :
4461 [ # # ]: 0 : if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
4462 : 0 : BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
4463 : : /* Don't call deinit since the prof_func wasn't allocated. */
4464 : 0 : rte_free(data);
4465 : 0 : return -ENOMEM;
4466 : : }
4467 : :
4468 : : /* Allocate the global resource ids */
4469 : 0 : rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
4470 [ # # ]: 0 : if (rc) {
4471 : 0 : BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
4472 : 0 : goto error;
4473 : : }
4474 : :
4475 : : /*
4476 : : * Only initialize the app global resources if a shared session was
4477 : : * created.
4478 : : */
4479 [ # # ]: 0 : if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) {
4480 : 0 : rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data);
4481 [ # # ]: 0 : if (rc) {
4482 : 0 : BNXT_TF_DBG(ERR, "Failed to init app glb resources\n");
4483 : 0 : goto error;
4484 : : }
4485 : : }
4486 : :
4487 : : /* Allocate the generic table list */
4488 : 0 : rc = ulp_mapper_generic_tbl_list_init(data);
4489 [ # # ]: 0 : if (rc) {
4490 : 0 : BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
4491 : 0 : goto error;
4492 : : }
4493 : :
4494 : : return 0;
4495 : 0 : error:
4496 : : /* Ignore the return code in favor of returning the original error. */
4497 : 0 : ulp_mapper_deinit(ulp_ctx);
4498 : 0 : return rc;
4499 : : }
4500 : :
4501 : : void
4502 : 0 : ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
4503 : : {
4504 : : struct bnxt_ulp_mapper_data *data;
4505 : : struct tf *tfp;
4506 : :
4507 [ # # ]: 0 : if (!ulp_ctx) {
4508 : 0 : BNXT_TF_DBG(ERR,
4509 : : "Failed to acquire ulp context, so data may not be released.\n");
4510 : 0 : return;
4511 : : }
4512 : :
4513 : : data = (struct bnxt_ulp_mapper_data *)
4514 : 0 : bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4515 [ # # ]: 0 : if (!data) {
4516 : : /* Go ahead and return since there is no allocated data. */
4517 : 0 : BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
4518 : 0 : return;
4519 : : }
4520 : :
4521 : 0 : tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT);
4522 [ # # ]: 0 : if (!tfp) {
4523 : 0 : BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
4524 : : /* Free the mapper data regardless of errors. */
4525 : 0 : goto free_mapper_data;
4526 : : }
4527 : :
4528 : : /* Free the global resource info table entries */
4529 : 0 : ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
4530 : :
4531 : 0 : free_mapper_data:
4532 : : /* Free the generic table */
4533 : 0 : (void)ulp_mapper_generic_tbl_list_deinit(data);
4534 : :
4535 : 0 : rte_free(data);
4536 : : /* Reset the data pointer within the ulp_ctx. */
4537 : 0 : bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
4538 : : }
|