1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2021 Broadcom
7 #include <rte_malloc.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"
15 #include "tf_ext_flow_handle.h"
16 #include "ulp_mark_mgr.h"
17 #include "ulp_mapper.h"
18 #include "ulp_flow_db.h"
20 #include "ulp_template_db_tbl.h"
22 static struct bnxt_ulp_glb_resource_info *
23 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
27 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
28 return ulp_glb_resource_tbl;
32 * Read the global resource from the mapper global resource list
34 * The regval is always returned in big-endian.
36 * returns 0 on success
39 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
44 if (!mapper_data || !regval ||
45 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
48 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
53 * Write a global resource to the mapper global resource list
55 * The regval value must be in big-endian.
57 * return 0 on success.
60 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
61 struct bnxt_ulp_glb_resource_info *res,
64 struct bnxt_ulp_mapper_glb_resource_entry *ent;
66 /* validate the arguments */
67 if (!data || res->direction >= TF_DIR_MAX ||
68 res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
71 /* write to the mapper data */
72 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
73 ent->resource_func = res->resource_func;
74 ent->resource_type = res->resource_type;
75 ent->resource_hndl = regval;
80 * Internal function to allocate identity resource and store it in mapper data.
82 * returns 0 on success
85 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
86 struct bnxt_ulp_mapper_data *mapper_data,
87 struct bnxt_ulp_glb_resource_info *glb_res)
89 struct tf_alloc_identifier_parms iparms = { 0 };
90 struct tf_free_identifier_parms fparms;
95 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
99 iparms.ident_type = glb_res->resource_type;
100 iparms.dir = glb_res->direction;
102 /* Allocate the Identifier using tf api */
103 rc = tf_alloc_identifier(tfp, &iparms);
105 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
106 tf_dir_2_str(iparms.dir),
111 /* entries are stored as big-endian format */
112 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
113 /* write to the mapper global resource */
114 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
116 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
117 /* Free the identifier when update failed */
118 fparms.dir = iparms.dir;
119 fparms.ident_type = iparms.ident_type;
120 fparms.id = iparms.id;
121 tf_free_identifier(tfp, &fparms);
128 * Internal function to allocate index tbl resource and store it in mapper data.
130 * returns 0 on success
133 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
134 struct bnxt_ulp_mapper_data *mapper_data,
135 struct bnxt_ulp_glb_resource_info *glb_res)
137 struct tf_alloc_tbl_entry_parms aparms = { 0 };
138 struct tf_free_tbl_entry_parms free_parms = { 0 };
141 uint32_t tbl_scope_id;
144 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
148 /* Get the scope id */
149 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
151 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
155 aparms.type = glb_res->resource_type;
156 aparms.dir = glb_res->direction;
157 aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
158 aparms.tbl_scope_id = tbl_scope_id;
160 /* Allocate the index tbl using tf api */
161 rc = tf_alloc_tbl_entry(tfp, &aparms);
163 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
164 tf_dir_2_str(aparms.dir), aparms.type);
168 /* entries are stored as big-endian format */
169 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
170 /* write to the mapper global resource */
171 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
173 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
174 /* Free the identifier when update failed */
175 free_parms.dir = aparms.dir;
176 free_parms.type = aparms.type;
177 free_parms.idx = aparms.idx;
178 tf_free_tbl_entry(tfp, &free_parms);
184 /* Retrieve the global template table */
186 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
190 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
191 return ulp_glb_template_tbl;
195 ulp_mapper_glb_field_tbl_get(uint32_t idx)
197 return &ulp_glb_field_tbl[idx];
201 * Get the size of the action property for a given index.
203 * idx [in] The index for the action property
205 * returns the size of the action property.
208 ulp_mapper_act_prop_size_get(uint32_t idx)
210 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
212 return ulp_act_prop_map_table[idx];
215 static struct bnxt_ulp_mapper_cond_info *
216 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
219 enum bnxt_ulp_cond_list_opc *opc)
222 const struct ulp_template_device_tbls *dev_tbls;
224 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
225 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
226 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
227 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
229 return &dev_tbls->cond_list[idx];
232 static struct bnxt_ulp_mapper_cond_info *
233 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
234 struct bnxt_ulp_mapper_tbl_info *tbl,
236 enum bnxt_ulp_cond_list_opc *opc)
239 const struct ulp_template_device_tbls *dev_tbls;
241 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
242 *num_tbls = tbl->execute_info.cond_nums;
243 *opc = tbl->execute_info.cond_list_opcode;
244 idx = tbl->execute_info.cond_start_idx;
246 return &dev_tbls->cond_list[idx];
250 * Get a list of classifier tables that implement the flow
251 * Gets a device dependent list of tables that implement the class template id
253 * mparms [in] The mappers parms with data related to the flow.
255 * tid [in] The template id that matches the flow
257 * num_tbls [out] The number of classifier tables in the returned array
259 * returns An array of classifier tables to implement the flow, or NULL on
262 static struct bnxt_ulp_mapper_tbl_info *
263 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
268 const struct ulp_template_device_tbls *dev_tbls;
270 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
272 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
273 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
275 return &dev_tbls->tbl_list[idx];
279 * Get the list of key fields that implement the flow.
281 * mparms [in] The mapper parms with information about the flow
283 * tbl [in] A single table instance to get the key fields from
285 * num_flds [out] The number of key fields in the returned array
287 * Returns array of Key fields, or NULL on error.
289 static struct bnxt_ulp_mapper_key_field_info *
290 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
291 struct bnxt_ulp_mapper_tbl_info *tbl,
295 const struct ulp_template_device_tbls *dev_tbls;
297 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
298 if (!dev_tbls->key_field_list) {
303 idx = tbl->key_start_idx;
304 *num_flds = tbl->key_num_fields;
306 return &dev_tbls->key_field_list[idx];
310 * Get the list of data fields that implement the flow.
312 * mparms [in] The mapper parms with information about the flow
314 * tbl [in] A single table instance to get the data fields from
316 * num_flds [out] The number of data fields in the returned array.
318 * num_encap_flds [out] The number of encap fields in the returned array.
320 * Returns array of data fields, or NULL on error.
322 static struct bnxt_ulp_mapper_result_field_info *
323 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
324 struct bnxt_ulp_mapper_tbl_info *tbl,
326 uint32_t *num_encap_flds)
329 const struct ulp_template_device_tbls *dev_tbls;
331 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
332 if (!dev_tbls->result_field_list) {
338 idx = tbl->result_start_idx;
339 *num_flds = tbl->result_num_fields;
340 *num_encap_flds = tbl->encap_num_fields;
342 return &dev_tbls->result_field_list[idx];
346 * Get the list of ident fields that implement the flow
348 * tbl [in] A single table instance to get the ident fields from
350 * num_flds [out] The number of ident fields in the returned array
352 * returns array of ident fields, or NULL on error
354 static struct bnxt_ulp_mapper_ident_info *
355 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
356 struct bnxt_ulp_mapper_tbl_info *tbl,
360 const struct ulp_template_device_tbls *dev_tbls;
362 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
363 if (!dev_tbls->ident_list) {
368 idx = tbl->ident_start_idx;
369 *num_flds = tbl->ident_nums;
371 return &dev_tbls->ident_list[idx];
374 static inline int32_t
375 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
377 struct ulp_flow_db_res_params *res)
379 struct tf_free_tcam_entry_parms fparms = {
380 .dir = res->direction,
381 .tcam_tbl_type = res->resource_type,
382 .idx = (uint16_t)res->resource_hndl
385 return tf_free_tcam_entry(tfp, &fparms);
388 static inline int32_t
389 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
391 struct ulp_flow_db_res_params *res)
393 struct tf_free_tbl_entry_parms fparms = {
394 .dir = res->direction,
395 .type = res->resource_type,
396 .idx = (uint32_t)res->resource_hndl
400 * Just get the table scope, it will be ignored if not necessary
401 * by the tf_free_tbl_entry
403 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
405 return tf_free_tbl_entry(tfp, &fparms);
408 static inline int32_t
409 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
411 struct ulp_flow_db_res_params *res)
413 struct tf_delete_em_entry_parms fparms = { 0 };
416 fparms.dir = res->direction;
417 if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)
418 fparms.mem = TF_MEM_EXTERNAL;
420 fparms.mem = TF_MEM_INTERNAL;
421 fparms.flow_handle = res->resource_hndl;
423 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
425 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
429 return tf_delete_em_entry(tfp, &fparms);
432 static inline int32_t
433 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
435 struct ulp_flow_db_res_params *res)
437 struct tf_free_identifier_parms fparms = {
438 .dir = res->direction,
439 .ident_type = res->resource_type,
440 .id = (uint16_t)res->resource_hndl
443 return tf_free_identifier(tfp, &fparms);
446 static inline int32_t
447 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
448 struct ulp_flow_db_res_params *res)
450 return ulp_mark_db_mark_del(ulp,
455 static inline int32_t
456 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
458 struct ulp_flow_db_res_params *res)
460 uint32_t idx, child_fid = 0, parent_idx;
461 struct bnxt_ulp_flow_db *flow_db;
463 parent_idx = (uint32_t)res->resource_hndl;
465 /* check the validity of the parent fid */
466 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
468 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
472 /* Clear all the child flows parent index */
473 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
474 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
476 /* update the child flows resource handle */
477 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
479 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
485 /* free the parent entry in the parent table flow */
486 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
487 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
493 static inline int32_t
494 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
496 struct ulp_flow_db_res_params *res)
500 parent_fid = (uint32_t)res->resource_hndl;
502 return 0; /* Already freed - orphan child*/
504 /* reset the child flow bitset*/
505 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
506 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
507 parent_fid, child_fid);
514 * Process the flow database opcode action.
515 * returns 0 on success.
518 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
519 struct bnxt_ulp_mapper_tbl_info *tbl,
520 struct ulp_flow_db_res_params *fid_parms)
522 uint32_t push_fid, fid = 0;
526 switch (tbl->fdb_opcode) {
527 case BNXT_ULP_FDB_OPC_PUSH:
528 push_fid = parms->fid;
530 case BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE:
531 /* allocate a new fid */
532 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
534 tbl->resource_func, &fid);
537 "Unable to allocate flow table entry\n");
540 /* Store the allocated fid in regfile*/
542 rc = ulp_regfile_write(parms->regfile, tbl->flow_db_operand,
543 tfp_cpu_to_be_64(val64));
545 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
546 tbl->flow_db_operand);
550 /* Use the allocated fid to update the flow resource */
553 case BNXT_ULP_FDB_OPC_PUSH_REGFILE:
554 /* get the fid from the regfile */
555 rc = ulp_regfile_read(parms->regfile, tbl->flow_db_operand,
558 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
559 tbl->flow_db_operand);
562 /* Use the extracted fid to update the flow resource */
563 push_fid = tfp_be_to_cpu_64((uint32_t)val64);
566 return rc; /* Nothing to be done */
569 /* Add the resource to the flow database */
570 rc = ulp_flow_db_resource_add(parms->ulp_ctx, parms->flow_type,
571 push_fid, fid_parms);
573 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
580 /* free the allocated fid */
582 ulp_flow_db_fid_free(parms->ulp_ctx,
583 BNXT_ULP_FDB_TYPE_REGULAR, fid);
588 * Process the identifier list in the given table.
589 * Extract the ident from the table entry and
590 * write it to the reg file.
591 * returns 0 on success.
594 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
595 struct bnxt_ulp_mapper_tbl_info *tbl,
597 uint32_t byte_data_size,
598 enum bnxt_ulp_byte_order byte_order)
600 struct bnxt_ulp_mapper_ident_info *idents;
601 uint32_t i, num_idents = 0;
604 /* validate the null arguments */
606 BNXT_TF_DBG(ERR, "invalid argument\n");
610 /* Get the ident list and process each one */
611 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
613 for (i = 0; i < num_idents; i++) {
614 /* check the size of the buffer for validation */
615 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
616 ULP_BYTE_2_BITS(byte_data_size) ||
617 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
618 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
619 idents[i].ident_bit_pos,
620 idents[i].ident_bit_size,
624 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
625 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
627 idents[i].ident_bit_pos,
628 idents[i].ident_bit_size);
630 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
631 idents[i].ident_bit_pos,
632 idents[i].ident_bit_size);
634 /* Write it to the regfile, val64 is already in big-endian*/
635 if (!ulp_regfile_write(parms->regfile,
636 idents[i].regfile_idx,
638 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
639 idents[i].regfile_idx);
647 * Process the identifier instruction and either store it in the flow database
648 * or return it in the val (if not NULL) on success. If val is NULL, the
649 * identifier is to be stored in the flow database.
652 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
653 struct bnxt_ulp_mapper_tbl_info *tbl,
654 struct bnxt_ulp_mapper_ident_info *ident,
657 struct ulp_flow_db_res_params fid_parms;
660 struct tf_alloc_identifier_parms iparms = { 0 };
661 struct tf_free_identifier_parms free_parms = { 0 };
665 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
667 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
671 idx = ident->regfile_idx;
673 iparms.ident_type = ident->ident_type;
674 iparms.dir = tbl->direction;
676 rc = tf_alloc_identifier(tfp, &iparms);
678 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
679 tf_dir_2_str(iparms.dir),
680 tf_ident_2_str(iparms.ident_type));
684 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
685 if (!ulp_regfile_write(parms->regfile, idx, id)) {
686 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
688 /* Need to free the identifier, so goto error */
692 /* Link the resource to the flow in the flow db */
694 memset(&fid_parms, 0, sizeof(fid_parms));
695 fid_parms.direction = tbl->direction;
696 fid_parms.resource_func = ident->resource_func;
697 fid_parms.resource_type = ident->ident_type;
698 fid_parms.resource_hndl = iparms.id;
699 fid_parms.critical_resource = tbl->critical_resource;
701 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
703 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
705 /* Need to free the identifier, so goto error */
714 /* Need to free the identifier */
715 free_parms.dir = tbl->direction;
716 free_parms.ident_type = ident->ident_type;
717 free_parms.id = iparms.id;
719 (void)tf_free_identifier(tfp, &free_parms);
721 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
723 tf_dir_2_str(tbl->direction));
728 * Process the identifier instruction and extract it from result blob.
729 * Increment the identifier reference count and store it in the flow database.
732 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
733 struct bnxt_ulp_mapper_tbl_info *tbl,
734 struct bnxt_ulp_mapper_ident_info *ident,
735 struct ulp_blob *res_blob)
737 struct ulp_flow_db_res_params fid_parms;
740 struct tf_search_identifier_parms sparms = { 0 };
741 struct tf_free_identifier_parms free_parms = { 0 };
745 /* Get the tfp from ulp context */
746 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
748 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
752 /* Extract the index from the result blob */
753 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
754 ident->ident_bit_pos, ident->ident_bit_size);
756 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
760 /* populate the search params and search identifier shadow table */
761 sparms.ident_type = ident->ident_type;
762 sparms.dir = tbl->direction;
763 /* convert the idx into cpu format */
764 sparms.search_id = tfp_be_to_cpu_32(idx);
766 /* Search identifier also increase the reference count */
767 rc = tf_search_identifier(tfp, &sparms);
769 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
770 tf_dir_2_str(sparms.dir),
771 tf_ident_2_str(sparms.ident_type),
776 /* Write it to the regfile */
777 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
778 if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
779 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
781 /* Need to free the identifier, so goto error */
785 /* Link the resource to the flow in the flow db */
786 memset(&fid_parms, 0, sizeof(fid_parms));
787 fid_parms.direction = tbl->direction;
788 fid_parms.resource_func = ident->resource_func;
789 fid_parms.resource_type = ident->ident_type;
790 fid_parms.resource_hndl = sparms.search_id;
791 fid_parms.critical_resource = tbl->critical_resource;
792 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
794 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
796 /* Need to free the identifier, so goto error */
803 /* Need to free the identifier */
804 free_parms.dir = tbl->direction;
805 free_parms.ident_type = ident->ident_type;
806 free_parms.id = sparms.search_id;
807 (void)tf_free_identifier(tfp, &free_parms);
808 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
810 tf_dir_2_str(tbl->direction), sparms.search_id);
815 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
817 struct bnxt_ulp_mapper_result_field_info *fld,
818 struct ulp_blob *blob,
821 uint16_t idx, size_idx;
823 uint16_t write_idx = blob->write_idx;
825 uint32_t val_size = 0, field_size = 0;
830 switch (fld->result_opcode) {
831 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
832 val = fld->result_operand;
833 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
834 BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
838 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP:
839 if (!ulp_operand_read(fld->result_operand,
840 (uint8_t *)&idx, sizeof(uint16_t))) {
841 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
844 idx = tfp_be_to_cpu_16(idx);
846 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
847 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
850 val = &parms->act_prop->act_details[idx];
851 field_size = ulp_mapper_act_prop_size_get(idx);
852 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
853 field_size = field_size -
854 ((fld->field_bit_size + 7) / 8);
857 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
858 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
862 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT:
863 if (!ulp_operand_read(fld->result_operand,
864 (uint8_t *)&act_bit, sizeof(uint64_t))) {
865 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
868 act_bit = tfp_be_to_cpu_64(act_bit);
869 memset(act_val, 0, sizeof(act_val));
870 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
872 if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) {
873 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
876 if (!ulp_blob_push(blob, act_val, fld->field_bit_size)) {
877 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
882 case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
883 if (!ulp_operand_read(fld->result_operand,
884 (uint8_t *)&idx, sizeof(uint16_t))) {
885 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
888 idx = tfp_be_to_cpu_16(idx);
890 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
891 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
894 val = &parms->act_prop->act_details[idx];
896 /* get the size index next */
897 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
898 (uint8_t *)&size_idx, sizeof(uint16_t))) {
899 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
902 size_idx = tfp_be_to_cpu_16(size_idx);
904 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
905 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
908 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
910 val_size = tfp_be_to_cpu_32(val_size);
911 val_size = ULP_BYTE_2_BITS(val_size);
912 ulp_blob_push_encap(blob, val, val_size);
914 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
915 if (!ulp_operand_read(fld->result_operand,
916 (uint8_t *)&idx, sizeof(uint16_t))) {
917 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
921 idx = tfp_be_to_cpu_16(idx);
922 /* Uninitialized regfile entries return 0 */
923 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
924 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
929 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size);
931 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
935 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
936 if (!ulp_operand_read(fld->result_operand,
939 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
942 idx = tfp_be_to_cpu_16(idx);
943 if (ulp_mapper_glb_resource_read(parms->mapper_data,
946 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
950 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size);
952 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
956 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
957 if (!ulp_operand_read(fld->result_operand,
960 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
963 idx = tfp_be_to_cpu_16(idx);
964 if (idx < BNXT_ULP_CF_IDX_LAST)
965 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
966 fld->field_bit_size);
968 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
972 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
973 if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) {
974 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
979 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST:
980 if (!ulp_operand_read(fld->result_operand,
981 (uint8_t *)&act_bit, sizeof(uint64_t))) {
982 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
985 act_bit = tfp_be_to_cpu_64(act_bit);
986 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
987 /* Action bit is set so consider operand_true */
988 if (!ulp_operand_read(fld->result_operand_true,
991 BNXT_TF_DBG(ERR, "%s operand read failed\n",
995 idx = tfp_be_to_cpu_16(idx);
996 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
997 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n",
1001 val = &parms->act_prop->act_details[idx];
1002 field_size = ulp_mapper_act_prop_size_get(idx);
1003 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
1004 field_size = field_size -
1005 ((fld->field_bit_size + 7) / 8);
1008 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1009 BNXT_TF_DBG(ERR, "%s push field failed\n",
1014 /* action bit is not set, use the operand false */
1015 val = fld->result_operand_false;
1016 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1017 BNXT_TF_DBG(ERR, "%s failed to add field\n",
1023 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST:
1024 if (!ulp_operand_read(fld->result_operand,
1025 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1026 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1029 act_bit = tfp_be_to_cpu_64(act_bit);
1030 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
1031 /* Action bit is set so consider operand_true */
1032 val = fld->result_operand_true;
1034 /* action bit is not set, use the operand false */
1035 val = fld->result_operand_false;
1037 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1038 BNXT_TF_DBG(ERR, "%s failed to add field\n",
1043 case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF:
1044 if (!ulp_operand_read(fld->result_operand,
1046 sizeof(uint16_t))) {
1047 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1050 idx = tfp_be_to_cpu_16(idx);
1051 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1052 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1055 /* check if the computed field is set */
1056 if (ULP_COMP_FLD_IDX_RD(parms, idx))
1057 val = fld->result_operand_true;
1059 val = fld->result_operand_false;
1061 /* read the appropriate computed field */
1062 if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) {
1063 BNXT_TF_DBG(ERR, "%s val operand read failed\n", name);
1066 idx = tfp_be_to_cpu_16(idx);
1067 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1068 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
1071 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1072 fld->field_bit_size);
1074 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1078 case BNXT_ULP_MAPPER_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST:
1079 if (!ulp_operand_read(fld->result_operand,
1080 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1081 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1084 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1085 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) {
1086 /* Header bit is set so consider operand_true */
1087 val = fld->result_operand_true;
1089 /* Header bit is not set, use the operand false */
1090 val = fld->result_operand_false;
1092 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
1093 BNXT_TF_DBG(ERR, "%s failed to add field\n",
1099 BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x at %d\n",
1100 fld->result_opcode, write_idx);
1107 * Result table process and fill the result blob.
1108 * data [out] - the result blob data
1111 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1112 struct bnxt_ulp_mapper_tbl_info *tbl,
1113 struct ulp_blob *data,
1116 struct bnxt_ulp_mapper_result_field_info *dflds;
1117 uint32_t i, num_flds = 0, encap_flds = 0;
1120 /* Get the result field list */
1121 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1124 /* validate the result field list counts */
1125 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1126 (!num_flds && !encap_flds)) || !dflds ||
1127 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1128 (!num_flds || encap_flds))) {
1129 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1130 num_flds, encap_flds);
1134 /* process the result fields, loop through them */
1135 for (i = 0; i < (num_flds + encap_flds); i++) {
1136 /* set the swap index if encap swap bit is enabled */
1137 if (parms->device_params->encap_byte_swap && encap_flds &&
1139 ulp_blob_encap_swap_idx_set(data);
1141 /* Process the result fields */
1142 rc = ulp_mapper_result_field_process(parms, tbl->direction,
1143 &dflds[i], data, name);
1145 BNXT_TF_DBG(ERR, "data field failed\n");
1150 /* if encap bit swap is enabled perform the bit swap */
1151 if (parms->device_params->encap_byte_swap && encap_flds)
1152 ulp_blob_perform_encap_swap(data);
1157 /* Function to alloc action record and set the table. */
1159 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
1161 struct bnxt_ulp_mapper_key_field_info *f,
1162 struct ulp_blob *blob,
1167 uint16_t idx, bitlen;
1170 struct ulp_regfile *regfile = parms->regfile;
1171 uint8_t *val = NULL;
1172 struct bnxt_ulp_mapper_key_field_info *fld = f;
1173 uint32_t field_size;
1176 operand = fld->spec_operand;
1177 opcode = fld->spec_opcode;
1179 operand = fld->mask_operand;
1180 opcode = fld->mask_opcode;
1183 bitlen = fld->field_bit_size;
1186 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
1188 if (!ulp_blob_push(blob, val, bitlen)) {
1189 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1193 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
1194 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1195 BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
1200 case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD:
1201 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1202 sizeof(uint16_t))) {
1203 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1206 idx = tfp_be_to_cpu_16(idx);
1208 val = parms->hdr_field[idx].spec;
1210 val = parms->hdr_field[idx].mask;
1213 * Need to account for how much data was pushed to the header
1214 * field vs how much is to be inserted in the key/mask.
1216 field_size = parms->hdr_field[idx].size;
1217 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1218 field_size = field_size - ((bitlen + 7) / 8);
1222 if (!ulp_blob_push(blob, val, bitlen)) {
1223 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1227 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
1228 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1229 sizeof(uint16_t))) {
1230 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1233 idx = tfp_be_to_cpu_16(idx);
1234 if (idx < BNXT_ULP_CF_IDX_LAST)
1235 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1238 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1242 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
1243 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1244 sizeof(uint16_t))) {
1245 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1248 idx = tfp_be_to_cpu_16(idx);
1250 if (!ulp_regfile_read(regfile, idx, &val64)) {
1251 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1256 val = ulp_blob_push_64(blob, &val64, bitlen);
1258 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1262 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
1263 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1264 sizeof(uint16_t))) {
1265 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1268 idx = tfp_be_to_cpu_16(idx);
1269 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1272 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1276 val = ulp_blob_push_64(blob, &val64, bitlen);
1278 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1283 BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n",
1291 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1292 struct bnxt_ulp_mapper_tbl_info *tbl,
1295 struct ulp_flow_db_res_params fid_parms;
1296 uint32_t mark, gfid, mark_flag;
1297 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1300 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1301 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1302 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1303 BNXT_ULP_ACTION_BIT_MARK)))
1304 return rc; /* no need to perform gfid process */
1306 /* Get the mark id details from action property */
1307 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1309 mark = tfp_be_to_cpu_32(mark);
1311 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1312 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1314 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1317 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1320 fid_parms.direction = tbl->direction;
1321 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1322 fid_parms.critical_resource = tbl->critical_resource;
1323 fid_parms.resource_type = mark_flag;
1324 fid_parms.resource_hndl = gfid;
1325 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1327 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1332 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1333 struct bnxt_ulp_mapper_tbl_info *tbl)
1335 struct ulp_flow_db_res_params fid_parms;
1336 uint32_t act_idx, mark, mark_flag;
1338 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1341 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1342 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1343 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1344 BNXT_ULP_ACTION_BIT_MARK)))
1345 return rc; /* no need to perform mark action process */
1347 /* Get the mark id details from action property */
1348 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1350 mark = tfp_be_to_cpu_32(mark);
1352 if (!ulp_regfile_read(parms->regfile,
1353 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1355 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1358 act_idx = tfp_be_to_cpu_64(val64);
1359 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1360 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1363 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1366 fid_parms.direction = tbl->direction;
1367 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1368 fid_parms.critical_resource = tbl->critical_resource;
1369 fid_parms.resource_type = mark_flag;
1370 fid_parms.resource_hndl = act_idx;
1371 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1373 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1378 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1379 struct bnxt_ulp_mapper_tbl_info *tbl)
1381 struct ulp_flow_db_res_params fid_parms;
1382 uint32_t act_idx, mark, mark_flag;
1384 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1387 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1388 mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION)
1389 return rc; /* no need to perform mark action process */
1391 /* Get the mark id details from the computed field of dev port id */
1392 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1394 /* Get the main action pointer */
1395 if (!ulp_regfile_read(parms->regfile,
1396 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1398 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1401 act_idx = tfp_be_to_cpu_64(val64);
1403 /* Set the mark flag to local fid and vfr flag */
1404 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1406 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1409 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1412 fid_parms.direction = tbl->direction;
1413 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1414 fid_parms.critical_resource = tbl->critical_resource;
1415 fid_parms.resource_type = mark_flag;
1416 fid_parms.resource_hndl = act_idx;
1417 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1419 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1423 /* Tcam table scan the identifier list and allocate each identifier */
1425 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1426 struct bnxt_ulp_mapper_tbl_info *tbl)
1428 struct bnxt_ulp_mapper_ident_info *idents;
1429 uint32_t num_idents;
1432 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1433 for (i = 0; i < num_idents; i++) {
1434 if (ulp_mapper_ident_process(parms, tbl,
1442 * Tcam table scan the identifier list and extract the identifier from
1446 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1447 struct bnxt_ulp_mapper_tbl_info *tbl,
1448 struct ulp_blob *data)
1450 struct bnxt_ulp_mapper_ident_info *idents;
1451 uint32_t num_idents = 0, i;
1455 * Extract the listed identifiers from the result field,
1456 * no need to allocate them.
1458 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1459 for (i = 0; i < num_idents; i++) {
1460 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1462 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1469 /* Internal function to write the tcam entry */
1471 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1472 struct bnxt_ulp_mapper_tbl_info *tbl,
1473 struct ulp_blob *key,
1474 struct ulp_blob *mask,
1475 struct ulp_blob *data,
1478 struct tf_set_tcam_entry_parms sparms = { 0 };
1483 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1485 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1489 sparms.dir = tbl->direction;
1490 sparms.tcam_tbl_type = tbl->resource_type;
1492 /* Already verified the key/mask lengths */
1493 sparms.key = ulp_blob_data_get(key, &tmplen);
1494 sparms.key_sz_in_bits = tmplen;
1495 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1496 sparms.result = ulp_blob_data_get(data, &tmplen);
1498 if (tbl->result_bit_size != tmplen) {
1499 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1500 tmplen, tbl->result_bit_size);
1503 sparms.result_sz_in_bits = tbl->result_bit_size;
1504 if (tf_set_tcam_entry(tfp, &sparms)) {
1505 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1506 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1507 tf_dir_2_str(sparms.dir), sparms.idx);
1512 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1514 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1521 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80
1522 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1523 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob,
1526 uint8_t mode[2] = {0x0, 0x0};
1527 uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE;
1530 /* Add the mode bits to the key and mask*/
1533 else if (mode_len > 2)
1536 size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode));
1537 for (idx = 0; idx < mode_len; idx++)
1538 ulp_blob_insert(blob, (size * idx), mode,
1539 ULP_BYTE_2_BITS(sizeof(mode)));
1540 ulp_blob_perform_64B_word_swap(blob);
1541 ulp_blob_perform_64B_byte_swap(blob);
1545 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1546 struct bnxt_ulp_mapper_tbl_info *tbl)
1548 struct bnxt_ulp_mapper_key_field_info *kflds;
1549 struct ulp_blob key, mask, data, update_data;
1550 uint32_t i, num_kflds;
1553 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1554 struct tf_search_tcam_entry_parms searchparms = { 0 };
1555 struct ulp_flow_db_res_params fid_parms = { 0 };
1556 struct tf_free_tcam_entry_parms free_parms = { 0 };
1558 uint16_t tmplen = 0;
1561 /* Skip this if table opcode is NOP */
1562 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1563 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1564 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1569 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1571 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1575 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1576 if (!kflds || !num_kflds) {
1577 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1581 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1582 parms->device_params->byte_order) ||
1583 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1584 parms->device_params->byte_order) ||
1585 !ulp_blob_init(&data, tbl->result_bit_size,
1586 parms->device_params->byte_order) ||
1587 !ulp_blob_init(&update_data, tbl->result_bit_size,
1588 parms->device_params->byte_order)) {
1589 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1593 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1594 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1595 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1598 /* create the key/mask */
1600 * NOTE: The WC table will require some kind of flag to handle the
1601 * mode bits within the key/mask
1603 for (i = 0; i < num_kflds; i++) {
1605 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1607 &key, 1, "TCAM Key");
1609 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1613 /* Setup the mask */
1614 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1616 &mask, 0, "TCAM Mask");
1618 BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1623 /* For wild card tcam perform the post process to swap the blob */
1624 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1625 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size);
1626 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size);
1629 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1630 /* allocate the tcam index */
1631 aparms.dir = tbl->direction;
1632 aparms.tcam_tbl_type = tbl->resource_type;
1633 aparms.key = ulp_blob_data_get(&key, &tmplen);
1634 aparms.key_sz_in_bits = tmplen;
1635 if (tbl->blob_key_bit_size != tmplen) {
1636 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1637 tmplen, tbl->blob_key_bit_size);
1641 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1642 if (tbl->blob_key_bit_size != tmplen) {
1643 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1644 tmplen, tbl->blob_key_bit_size);
1647 aparms.priority = tbl->priority;
1648 rc = tf_alloc_tcam_entry(tfp, &aparms);
1650 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1657 * Searching before allocation to see if we already have an
1658 * entry. This allows re-use of a constrained resource.
1660 searchparms.dir = tbl->direction;
1661 searchparms.tcam_tbl_type = tbl->resource_type;
1662 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1663 searchparms.key_sz_in_bits = tbl->key_bit_size;
1664 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1665 searchparms.priority = tbl->priority;
1666 searchparms.alloc = 1;
1667 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1668 searchparms.result_sz_in_bits = tbl->result_bit_size;
1670 rc = tf_search_tcam_entry(tfp, &searchparms);
1672 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1676 /* Successful search, check the result */
1677 if (searchparms.search_status == REJECT) {
1678 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1681 idx = searchparms.idx;
1682 hit = searchparms.hit;
1685 /* Write the tcam index into the regfile*/
1686 if (!ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1687 (uint64_t)tfp_cpu_to_be_64(idx))) {
1688 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1691 /* Need to free the tcam idx, so goto error */
1695 /* if it is miss then it is same as no search before alloc */
1696 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1697 /*Scan identifier list, allocate identifier and update regfile*/
1698 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1699 /* Create the result blob */
1701 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1703 /* write the tcam entry */
1705 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1708 /*Scan identifier list, extract identifier and update regfile*/
1709 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1714 /* Add the tcam index to the flow database */
1715 fid_parms.direction = tbl->direction;
1716 fid_parms.resource_func = tbl->resource_func;
1717 fid_parms.resource_type = tbl->resource_type;
1718 fid_parms.critical_resource = tbl->critical_resource;
1719 fid_parms.resource_hndl = idx;
1720 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1722 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1724 /* Need to free the identifier, so goto error */
1730 free_parms.dir = tbl->direction;
1731 free_parms.tcam_tbl_type = tbl->resource_type;
1732 free_parms.idx = idx;
1733 trc = tf_free_tcam_entry(tfp, &free_parms);
1735 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1736 tbl->resource_type, tbl->direction, idx);
1741 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1742 struct bnxt_ulp_mapper_tbl_info *tbl)
1744 struct bnxt_ulp_mapper_key_field_info *kflds;
1745 struct ulp_blob key, data;
1746 uint32_t i, num_kflds;
1748 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1749 struct ulp_flow_db_res_params fid_parms = { 0 };
1750 struct tf_insert_em_entry_parms iparms = { 0 };
1751 struct tf_delete_em_entry_parms free_parms = { 0 };
1752 enum bnxt_ulp_flow_mem_type mtype;
1756 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1758 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1762 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1763 if (!kflds || !num_kflds) {
1764 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1768 /* Initialize the key/result blobs */
1769 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1770 parms->device_params->byte_order) ||
1771 !ulp_blob_init(&data, tbl->result_bit_size,
1772 parms->device_params->byte_order)) {
1773 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1777 /* create the key */
1778 for (i = 0; i < num_kflds; i++) {
1780 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1784 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1790 * TBD: Normally should process identifiers in case of using recycle or
1791 * loopback. Not supporting recycle for now.
1794 /* Create the result data blob */
1795 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1797 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1800 /* do the transpose for the internal EM keys */
1801 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1802 ulp_blob_perform_byte_reverse(&key);
1804 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1805 &iparms.tbl_scope_id);
1807 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1812 * NOTE: the actual blob size will differ from the size in the tbl
1813 * entry due to the padding.
1815 iparms.dup_check = 0;
1816 iparms.dir = tbl->direction;
1817 iparms.mem = tbl->resource_type;
1818 iparms.key = ulp_blob_data_get(&key, &tmplen);
1819 iparms.key_sz_in_bits = tbl->key_bit_size;
1820 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
1821 iparms.em_record_sz_in_bits = tbl->result_bit_size;
1823 rc = tf_insert_em_entry(tfp, &iparms);
1825 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1829 /* Mark action process */
1830 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1831 tbl->resource_type == TF_MEM_EXTERNAL)
1832 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1833 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1834 tbl->resource_type == TF_MEM_INTERNAL)
1835 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1837 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1841 /* Link the EM resource to the flow in the flow db */
1842 memset(&fid_parms, 0, sizeof(fid_parms));
1843 fid_parms.direction = tbl->direction;
1844 fid_parms.resource_func = tbl->resource_func;
1845 fid_parms.resource_type = tbl->resource_type;
1846 fid_parms.critical_resource = tbl->critical_resource;
1847 fid_parms.resource_hndl = iparms.flow_handle;
1849 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1851 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1853 /* Need to free the identifier, so goto error */
1859 free_parms.dir = iparms.dir;
1860 free_parms.mem = iparms.mem;
1861 free_parms.tbl_scope_id = iparms.tbl_scope_id;
1862 free_parms.flow_handle = iparms.flow_handle;
1864 trc = tf_delete_em_entry(tfp, &free_parms);
1866 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1872 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1873 struct bnxt_ulp_mapper_tbl_info *tbl)
1875 struct ulp_flow_db_res_params fid_parms;
1876 struct ulp_blob data;
1877 uint64_t regval = 0;
1879 uint32_t index, hit;
1880 int32_t rc = 0, trc = 0;
1881 struct tf_alloc_tbl_entry_parms aparms = { 0 };
1882 struct tf_search_tbl_entry_parms srchparms = { 0 };
1883 struct tf_set_tbl_entry_parms sparms = { 0 };
1884 struct tf_get_tbl_entry_parms gparms = { 0 };
1885 struct tf_free_tbl_entry_parms free_parms = { 0 };
1886 uint32_t tbl_scope_id;
1887 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1891 bool search = false;
1893 /* use the max size if encap is enabled */
1894 if (tbl->encap_num_fields)
1895 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1897 bit_size = tbl->result_bit_size;
1899 /* Initialize the blob data */
1900 if (!ulp_blob_init(&data, bit_size,
1901 parms->device_params->byte_order)) {
1902 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
1906 /* Get the scope id first */
1907 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1909 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1913 switch (tbl->tbl_opcode) {
1914 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
1917 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
1919 * Build the entry, alloc an index, write the table, and store
1920 * the data in the regfile.
1925 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
1926 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1927 /* Not currently supporting with EXT */
1929 "Ext Table Search Opcode not supported.\n");
1933 * Search for the entry in the tf core. If it is hit, save the
1934 * index in the regfile. If it is a miss, Build the entry,
1935 * alloc an index, write the table, and store the data in the
1936 * regfile (same as ALLOC_WR).
1940 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
1942 * get the index to write to from the regfile and then write
1945 if (!ulp_regfile_read(parms->regfile,
1949 "Failed to get tbl idx from regfile[%d].\n",
1953 index = tfp_be_to_cpu_64(regval);
1954 /* For external, we need to reverse shift */
1955 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1956 index = TF_ACT_REC_PTR_2_OFFSET(index);
1960 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
1962 * get the index to write to from the global regfile and then
1965 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1970 "Failed to get tbl idx from Global "
1972 tbl->index_operand);
1975 index = tfp_be_to_cpu_64(regval);
1976 /* For external, we need to reverse shift */
1977 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1978 index = TF_ACT_REC_PTR_2_OFFSET(index);
1981 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
1983 * The read is different from the rest and can be handled here
1984 * instead of trying to use common code. Simply read the table
1985 * with the index from the regfile, scan and store the
1986 * identifiers, and return.
1988 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
1989 /* Not currently supporting with EXT */
1991 "Ext Table Read Opcode not supported.\n");
1994 if (!ulp_regfile_read(parms->regfile,
1995 tbl->tbl_operand, ®val)) {
1997 "Failed to get tbl idx from regfile[%d]\n",
2001 index = tfp_be_to_cpu_64(regval);
2002 gparms.dir = tbl->direction;
2003 gparms.type = tbl->resource_type;
2004 gparms.data = ulp_blob_data_get(&data, &tmplen);
2005 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2007 rc = tf_get_tbl_entry(tfp, &gparms);
2009 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2010 tbl->resource_type, index);
2014 * Scan the fields in the entry and push them into the regfile.
2016 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2018 gparms.data_sz_in_bytes,
2021 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2027 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2032 if (write || search) {
2033 /* Get the result fields list */
2034 rc = ulp_mapper_tbl_result_build(parms,
2039 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2045 /* Use the result blob to perform a search */
2046 memset(&srchparms, 0, sizeof(srchparms));
2047 srchparms.dir = tbl->direction;
2048 srchparms.type = tbl->resource_type;
2049 srchparms.alloc = 1;
2050 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2051 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2052 srchparms.tbl_scope_id = tbl_scope_id;
2053 rc = tf_search_tbl_entry(tfp, &srchparms);
2055 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2056 tf_tbl_type_2_str(tbl->resource_type),
2057 tf_dir_2_str(tbl->direction), rc);
2060 if (srchparms.search_status == REJECT) {
2061 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2062 tf_tbl_type_2_str(tbl->resource_type),
2063 tf_dir_2_str(tbl->direction));
2066 index = srchparms.idx;
2067 hit = srchparms.hit;
2075 aparms.dir = tbl->direction;
2076 aparms.type = tbl->resource_type;
2077 aparms.tbl_scope_id = tbl_scope_id;
2079 /* All failures after the alloc succeeds require a free */
2080 rc = tf_alloc_tbl_entry(tfp, &aparms);
2082 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2083 tf_tbl_type_2_str(tbl->resource_type),
2084 tf_dir_2_str(tbl->direction), rc);
2090 if (search || alloc) {
2092 * Store the index in the regfile since we either allocated it
2095 * Calculate the idx for the result record, for external EM the
2096 * offset needs to be shifted accordingly.
2097 * If external non-inline table types are used then need to
2098 * revisit this logic.
2100 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2101 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2105 rc = ulp_regfile_write(parms->regfile,
2107 tfp_cpu_to_be_64(regval));
2109 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2110 tbl->tbl_operand, rc);
2116 sparms.dir = tbl->direction;
2117 sparms.type = tbl->resource_type;
2118 sparms.data = ulp_blob_data_get(&data, &tmplen);
2119 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2121 sparms.tbl_scope_id = tbl_scope_id;
2122 rc = tf_set_tbl_entry(tfp, &sparms);
2125 "Index table[%s][%s][%x] write failed "
2127 tf_tbl_type_2_str(sparms.type),
2128 tf_dir_2_str(sparms.dir),
2134 /* Link the resource to the flow in the flow db */
2135 memset(&fid_parms, 0, sizeof(fid_parms));
2136 fid_parms.direction = tbl->direction;
2137 fid_parms.resource_func = tbl->resource_func;
2138 fid_parms.resource_type = tbl->resource_type;
2139 fid_parms.resource_sub_type = tbl->resource_sub_type;
2140 fid_parms.resource_hndl = index;
2141 fid_parms.critical_resource = tbl->critical_resource;
2143 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2145 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2150 /* Perform the VF rep action */
2151 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2153 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2159 * Free the allocated resource since we failed to either
2160 * write to the entry or link the flow
2162 free_parms.dir = tbl->direction;
2163 free_parms.type = tbl->resource_type;
2164 free_parms.idx = index;
2165 free_parms.tbl_scope_id = tbl_scope_id;
2167 trc = tf_free_tbl_entry(tfp, &free_parms);
2169 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2175 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2176 struct bnxt_ulp_mapper_tbl_info *tbl)
2178 struct ulp_blob data, res_blob;
2182 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2183 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2184 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2185 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2188 /* Initialize the blob data */
2189 if (!ulp_blob_init(&data, tbl->result_bit_size,
2190 parms->device_params->byte_order)) {
2191 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2195 /* create the result blob */
2196 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2198 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2202 /* Get the index details */
2204 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2205 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2207 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2208 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2209 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2213 idx = tfp_be_to_cpu_64(idx);
2215 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2216 idx = tbl->tbl_operand;
2218 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2219 /* Initialize the result blob */
2220 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2221 parms->device_params->byte_order)) {
2222 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2226 /* read the interface table */
2227 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2228 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2229 get_parms.dir = tbl->direction;
2230 get_parms.type = tbl->resource_type;
2231 get_parms.idx = idx;
2232 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2233 get_parms.data_sz_in_bytes = res_size;
2235 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2237 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2239 tf_dir_2_str(get_parms.dir),
2243 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2246 res_blob.byte_order);
2248 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2250 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2251 return rc; /* skip it */
2253 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2257 /* Perform the tf table set by filling the set params */
2258 iftbl_params.dir = tbl->direction;
2259 iftbl_params.type = tbl->resource_type;
2260 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2261 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2262 iftbl_params.idx = idx;
2264 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2266 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2267 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2268 tf_dir_2_str(iftbl_params.dir),
2269 iftbl_params.idx, rc);
2274 * TBD: Need to look at the need to store idx in flow db for restore
2275 * the table to its original state on deletion of this entry.
2281 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2282 struct bnxt_ulp_mapper_tbl_info *tbl)
2284 struct bnxt_ulp_mapper_key_field_info *kflds;
2285 struct ulp_flow_db_res_params fid_parms;
2286 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2288 struct ulp_blob key, data;
2291 uint32_t i, ckey, num_kflds = 0;
2292 uint32_t gen_tbl_hit = 0, fdb_write = 0;
2296 /* Get the key fields list and build the key. */
2297 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2298 if (!kflds || !num_kflds) {
2299 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2302 if (!ulp_blob_init(&key, tbl->key_bit_size,
2303 parms->device_params->byte_order)) {
2304 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2307 for (i = 0; i < num_kflds; i++) {
2309 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
2311 &key, 1, "Gen Tbl Key");
2314 "Failed to create key for Gen tbl rc=%d\n",
2320 /* Calculate the table index for the generic table*/
2321 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2324 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2325 tbl->resource_sub_type, tbl->direction);
2329 /* The_key is a byte array convert it to a search index */
2330 cache_key = ulp_blob_data_get(&key, &tmplen);
2331 memcpy(&ckey, cache_key, sizeof(ckey));
2332 /* Get the generic table entry */
2333 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2334 tbl_idx, ckey, &gen_tbl_ent);
2337 "Failed to create key for Gen tbl rc=%d\n", rc);
2340 switch (tbl->tbl_opcode) {
2341 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2342 /* check the reference count */
2343 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2345 /* Scan ident list and create the result blob*/
2346 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2352 "Failed to scan ident list\n");
2355 /* increment the reference count */
2356 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2363 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2364 /* check the reference count */
2365 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2366 /* a hit then error */
2367 BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2369 return -EINVAL; /* success */
2372 /* Initialize the blob data */
2373 if (!ulp_blob_init(&data, tbl->result_bit_size,
2374 BNXT_ULP_BYTE_ORDER_BE)) {
2375 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2379 /* Get the result fields list */
2380 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2383 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2386 byte_data = ulp_blob_data_get(&data, &tmplen);
2387 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, 0,
2389 ULP_BITS_2_BYTE(tmplen));
2391 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2395 /* increment the reference count */
2396 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2400 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2404 /* Set the generic entry hit */
2405 rc = ulp_regfile_write(parms->regfile,
2406 BNXT_ULP_REGFILE_INDEX_GENERIC_TBL_HIT,
2407 tfp_cpu_to_be_64(gen_tbl_hit));
2409 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2410 tbl->index_operand);
2414 /* add the entry to the flow database */
2416 memset(&fid_parms, 0, sizeof(fid_parms));
2417 fid_parms.direction = tbl->direction;
2418 fid_parms.resource_func = tbl->resource_func;
2419 fid_parms.resource_sub_type = tbl->resource_sub_type;
2420 fid_parms.resource_hndl = ckey;
2421 fid_parms.critical_resource = tbl->critical_resource;
2422 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2424 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2430 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2431 struct bnxt_ulp_mapper_data *mapper_data)
2433 struct bnxt_ulp_glb_resource_info *glb_res;
2434 uint32_t num_glb_res_ids, idx;
2437 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2438 if (!glb_res || !num_glb_res_ids) {
2439 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2443 /* Iterate the global resources and process each one */
2444 for (idx = 0; idx < num_glb_res_ids; idx++) {
2445 switch (glb_res[idx].resource_func) {
2446 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2447 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2451 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2452 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2457 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2458 glb_res[idx].resource_func);
2469 * Function to process the memtype opcode of the mapper table.
2470 * returns 1 to skip the table.
2471 * return 0 to continue processing the table.
2476 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2477 struct bnxt_ulp_mapper_tbl_info *tbl)
2479 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2482 bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2484 switch (tbl->mem_type_opcode) {
2485 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_INT:
2486 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2489 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_EXT:
2490 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2493 case BNXT_ULP_MEM_TYPE_OPCODE_NOP:
2498 "Invalid arg in mapper in memtype opcode\n");
2505 * Common conditional opcode process routine that is used for both the template
2506 * rejection and table conditional execution.
2509 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2510 enum bnxt_ulp_cond_opc opc,
2520 case BNXT_ULP_COND_OPC_COMP_FIELD_IS_SET:
2521 if (operand < BNXT_ULP_CF_IDX_LAST) {
2522 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2524 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2529 case BNXT_ULP_COND_OPC_COMP_FIELD_NOT_SET:
2530 if (operand < BNXT_ULP_CF_IDX_LAST) {
2531 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2533 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2538 case BNXT_ULP_COND_OPC_ACTION_BIT_IS_SET:
2539 if (operand < BNXT_ULP_ACTION_BIT_LAST) {
2540 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2543 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2548 case BNXT_ULP_COND_OPC_ACTION_BIT_NOT_SET:
2549 if (operand < BNXT_ULP_ACTION_BIT_LAST) {
2550 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2553 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2558 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2559 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2560 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2563 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2568 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2569 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2570 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2573 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2578 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2579 idx = (parms->class_tid << BNXT_ULP_GLB_FIELD_TBL_SHIFT) |
2581 bit = ulp_mapper_glb_field_tbl_get(idx);
2583 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2587 *res = ULP_BITMAP_ISSET(parms->fld_bitmap->bits, (1 << *bit));
2589 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2590 idx = (parms->class_tid << BNXT_ULP_GLB_FIELD_TBL_SHIFT) |
2592 bit = ulp_mapper_glb_field_tbl_get(idx);
2594 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2598 *res = !ULP_BITMAP_ISSET(parms->fld_bitmap->bits, (1 << *bit));
2600 case BNXT_ULP_COND_OPC_REGFILE_IS_SET:
2601 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2602 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2607 case BNXT_ULP_COND_OPC_REGFILE_NOT_SET:
2608 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2609 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2615 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2623 * Processes a list of conditions and returns both a status and result of the
2624 * list. The status must be checked prior to verifying the result.
2626 * returns 0 for success, negative on failure
2627 * returns res = 1 for true, res = 0 for false.
2630 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2631 enum bnxt_ulp_cond_list_opc list_opc,
2632 struct bnxt_ulp_mapper_cond_info *list,
2637 int32_t rc = 0, trc;
2640 case BNXT_ULP_COND_LIST_OPC_AND:
2641 /* AND Defaults to true. */
2644 case BNXT_ULP_COND_LIST_OPC_OR:
2645 /* OR Defaults to false. */
2648 case BNXT_ULP_COND_LIST_OPC_TRUE:
2651 case BNXT_ULP_COND_LIST_OPC_FALSE:
2655 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2660 for (i = 0; i < num; i++) {
2661 rc = ulp_mapper_cond_opc_process(parms,
2662 list[i].cond_opcode,
2663 list[i].cond_operand,
2668 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2669 /* early return if result is ever zero */
2675 /* early return if result is ever non-zero */
2687 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2689 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2690 enum bnxt_ulp_cond_list_opc cond_opc;
2691 struct bnxt_ulp_mapper_tbl_info *tbls;
2692 struct bnxt_ulp_mapper_tbl_info *tbl;
2693 uint32_t num_tbls, i, num_cond_tbls;
2694 int32_t rc = -EINVAL, cond_rc = 0;
2696 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
2700 * Process the reject list if exists, otherwise assume that the
2701 * template is allowed.
2703 if (cond_tbls && num_cond_tbls) {
2704 rc = ulp_mapper_cond_opc_list_process(parms,
2712 /* Reject the template if True */
2714 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
2715 (parms->tmpl_type ==
2716 BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2717 "class" : "action", tid);
2722 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2723 if (!tbls || !num_tbls) {
2724 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2725 (parms->tmpl_type == BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2726 "class" : "action", parms->dev_id, tid);
2730 for (i = 0; i < num_tbls; i++) {
2733 /* Handle the table level opcodes to determine if required. */
2734 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl))
2736 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
2739 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
2740 cond_tbls, num_cond_tbls,
2743 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
2747 /* Skip the table if False */
2751 switch (tbl->resource_func) {
2752 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2753 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2755 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2756 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2757 rc = ulp_mapper_em_tbl_process(parms, tbl);
2759 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2760 rc = ulp_mapper_index_tbl_process(parms, tbl);
2762 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2763 rc = ulp_mapper_if_tbl_process(parms, tbl);
2765 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2766 rc = ulp_mapper_gen_tbl_process(parms, tbl);
2768 case BNXT_ULP_RESOURCE_FUNC_INVALID:
2772 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
2773 tbl->resource_func);
2779 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2780 tbl->resource_func);
2787 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
2788 (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2789 "class" : "action", parms->dev_id, tid);
2794 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2796 struct ulp_flow_db_res_params *res)
2802 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2806 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2808 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2812 switch (res->resource_func) {
2813 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2814 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2816 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2817 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2818 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
2820 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2821 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2823 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2824 rc = ulp_mapper_ident_free(ulp, tfp, res);
2826 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2827 rc = ulp_mapper_mark_free(ulp, res);
2829 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
2830 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
2832 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
2833 rc = ulp_mapper_child_flow_free(ulp, fid, res);
2835 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2836 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
2846 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
2847 enum bnxt_ulp_fdb_type flow_type,
2850 struct ulp_flow_db_res_params res_parms = { 0 };
2854 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2859 * Set the critical resource on the first resource del, then iterate
2860 * while status is good
2862 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2863 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
2867 * This is unexpected on the first call to resource del.
2868 * It likely means that the flow did not exist in the flow db.
2870 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2871 flow_type, fid, rc);
2876 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
2879 * On fail, we still need to attempt to free the
2880 * remaining resources. Don't return
2883 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2884 "] failed rc=%d.\n",
2885 flow_type, fid, res_parms.resource_func,
2886 res_parms.resource_hndl, trc);
2888 /* All subsequent call require the non-critical_resource */
2889 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2891 rc = ulp_flow_db_resource_del(ulp_ctx,
2897 /* Free the Flow ID since we've removed all resources */
2898 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
2904 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2905 struct bnxt_ulp_mapper_data *mapper_data)
2907 struct bnxt_ulp_mapper_glb_resource_entry *ent;
2908 struct ulp_flow_db_res_params res;
2911 /* Iterate the global resources and process each one */
2912 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2913 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
2915 ent = &mapper_data->glb_res_tbl[dir][idx];
2916 if (ent->resource_func ==
2917 BNXT_ULP_RESOURCE_FUNC_INVALID)
2919 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2920 res.resource_func = ent->resource_func;
2921 res.direction = dir;
2922 res.resource_type = ent->resource_type;
2923 /*convert it from BE to cpu */
2925 tfp_be_to_cpu_64(ent->resource_hndl);
2926 ulp_mapper_resource_free(ulp_ctx, 0, &res);
2932 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
2933 enum bnxt_ulp_fdb_type flow_type,
2939 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2943 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
2947 /* Function to handle the default global templates that are allocated during
2948 * the startup and reused later.
2951 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
2953 uint32_t *glbl_tmpl_list;
2954 uint32_t num_glb_tmpls, idx, dev_id;
2955 struct bnxt_ulp_mapper_parms parms;
2956 struct bnxt_ulp_mapper_data *mapper_data;
2959 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
2960 if (!glbl_tmpl_list || !num_glb_tmpls)
2961 return rc; /* No global templates to process */
2963 /* Get the device id from the ulp context */
2964 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
2965 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2969 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2971 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2975 /* Iterate the global resources and process each one */
2976 for (idx = 0; idx < num_glb_tmpls; idx++) {
2977 /* Initialize the parms structure */
2978 memset(&parms, 0, sizeof(parms));
2979 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2980 parms.ulp_ctx = ulp_ctx;
2981 parms.dev_id = dev_id;
2982 parms.mapper_data = mapper_data;
2983 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
2984 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2986 /* Get the class table entry from dev id and class id */
2987 parms.class_tid = glbl_tmpl_list[idx];
2989 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2990 if (!parms.device_params) {
2991 BNXT_TF_DBG(ERR, "No device for device id %d\n",
2996 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3003 /* Function to handle the mapping of the Flow to be compatible
3004 * with the underlying hardware.
3007 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3008 struct bnxt_ulp_mapper_create_parms *cparms)
3010 struct bnxt_ulp_mapper_parms parms;
3011 struct ulp_regfile regfile;
3014 if (!ulp_ctx || !cparms)
3017 /* Initialize the parms structure */
3018 memset(&parms, 0, sizeof(parms));
3019 parms.act_prop = cparms->act_prop;
3020 parms.act_bitmap = cparms->act;
3021 parms.hdr_bitmap = cparms->hdr_bitmap;
3022 parms.regfile = ®file;
3023 parms.hdr_field = cparms->hdr_field;
3024 parms.comp_fld = cparms->comp_fld;
3025 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3026 parms.ulp_ctx = ulp_ctx;
3027 parms.act_tid = cparms->act_tid;
3028 parms.class_tid = cparms->class_tid;
3029 parms.flow_type = cparms->flow_type;
3030 parms.parent_flow = cparms->parent_flow;
3031 parms.parent_fid = cparms->parent_fid;
3032 parms.fid = cparms->flow_id;
3033 parms.tun_idx = cparms->tun_idx;
3035 /* Get the device id from the ulp context */
3036 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3037 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3041 /* Get the device params, it will be used in later processing */
3042 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3043 if (!parms.device_params) {
3044 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3050 * Get the mapper data for dynamic mapper data such as default
3053 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3054 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3055 if (!parms.mapper_data) {
3056 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3060 /* initialize the registry file for further processing */
3061 if (!ulp_regfile_init(parms.regfile)) {
3062 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3066 rc = ulp_regfile_write(parms.regfile,
3067 BNXT_ULP_REGFILE_INDEX_CLASS_TID,
3068 tfp_cpu_to_be_64((uint64_t)parms.class_tid));
3070 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
3074 /* Process the action template list from the selected action table*/
3075 if (parms.act_tid) {
3076 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3077 /* Process the action template tables */
3078 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3083 if (parms.class_tid) {
3084 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3086 /* Process the class template tables.*/
3087 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3092 /* setup the parent-child details */
3093 if (parms.parent_flow) {
3094 /* create a parent flow details */
3095 rc = ulp_flow_db_parent_flow_create(&parms);
3098 } else if (parms.parent_fid) {
3099 /* create a child flow details */
3100 rc = ulp_flow_db_child_flow_create(&parms);
3108 /* Free all resources that were allocated during flow creation */
3109 trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
3112 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3118 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3120 struct bnxt_ulp_mapper_data *data;
3127 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3131 data = rte_zmalloc("ulp_mapper_data",
3132 sizeof(struct bnxt_ulp_mapper_data), 0);
3134 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3138 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3139 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3140 /* Don't call deinit since the prof_func wasn't allocated. */
3145 /* Allocate the global resource ids */
3146 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3148 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3152 /* Allocate the generic table list */
3153 rc = ulp_mapper_generic_tbl_list_init(data);
3155 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3159 /* Allocate global template table entries */
3160 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3162 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3168 /* Ignore the return code in favor of returning the original error. */
3169 ulp_mapper_deinit(ulp_ctx);
3174 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3176 struct bnxt_ulp_mapper_data *data;
3181 "Failed to acquire ulp context, so data may "
3182 "not be released.\n");
3186 data = (struct bnxt_ulp_mapper_data *)
3187 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3189 /* Go ahead and return since there is no allocated data. */
3190 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3194 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3196 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3197 /* Free the mapper data regardless of errors. */
3198 goto free_mapper_data;
3201 /* Free the global resource info table entries */
3202 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3205 /* Free the generic table */
3206 (void)ulp_mapper_generic_tbl_list_deinit(data);
3209 /* Reset the data pointer within the ulp_ctx. */
3210 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);