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 uint8_t mapper_fld_ones[16] = {
23 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
24 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
28 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
31 case BNXT_ULP_TEMPLATE_TYPE_CLASS:
33 case BNXT_ULP_TEMPLATE_TYPE_ACTION:
36 return "invalid template type";
41 static struct bnxt_ulp_glb_resource_info *
42 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
46 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
47 return ulp_glb_resource_tbl;
51 * Read the global resource from the mapper global resource list
53 * The regval is always returned in big-endian.
55 * returns 0 on success
58 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
63 if (!mapper_data || !regval ||
64 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
67 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
72 * Write a global resource to the mapper global resource list
74 * The regval value must be in big-endian.
76 * return 0 on success.
79 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
80 struct bnxt_ulp_glb_resource_info *res,
83 struct bnxt_ulp_mapper_glb_resource_entry *ent;
85 /* validate the arguments */
86 if (!data || res->direction >= TF_DIR_MAX ||
87 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
90 /* write to the mapper data */
91 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
92 ent->resource_func = res->resource_func;
93 ent->resource_type = res->resource_type;
94 ent->resource_hndl = regval;
99 * Internal function to allocate identity resource and store it in mapper data.
101 * returns 0 on success
104 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
105 struct bnxt_ulp_mapper_data *mapper_data,
106 struct bnxt_ulp_glb_resource_info *glb_res)
108 struct tf_alloc_identifier_parms iparms = { 0 };
109 struct tf_free_identifier_parms fparms;
114 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
118 iparms.ident_type = glb_res->resource_type;
119 iparms.dir = glb_res->direction;
121 /* Allocate the Identifier using tf api */
122 rc = tf_alloc_identifier(tfp, &iparms);
124 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
125 tf_dir_2_str(iparms.dir),
130 /* entries are stored as big-endian format */
131 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
132 /* write to the mapper global resource */
133 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
135 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
136 /* Free the identifier when update failed */
137 fparms.dir = iparms.dir;
138 fparms.ident_type = iparms.ident_type;
139 fparms.id = iparms.id;
140 tf_free_identifier(tfp, &fparms);
147 * Internal function to allocate index tbl resource and store it in mapper data.
149 * returns 0 on success
152 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
153 struct bnxt_ulp_mapper_data *mapper_data,
154 struct bnxt_ulp_glb_resource_info *glb_res)
156 struct tf_alloc_tbl_entry_parms aparms = { 0 };
157 struct tf_free_tbl_entry_parms free_parms = { 0 };
160 uint32_t tbl_scope_id;
163 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
167 /* Get the scope id */
168 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
170 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
174 aparms.type = glb_res->resource_type;
175 aparms.dir = glb_res->direction;
176 aparms.search_enable = 0;
177 aparms.tbl_scope_id = tbl_scope_id;
179 /* Allocate the index tbl using tf api */
180 rc = tf_alloc_tbl_entry(tfp, &aparms);
182 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
183 tf_dir_2_str(aparms.dir), aparms.type);
187 /* entries are stored as big-endian format */
188 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
189 /* write to the mapper global resource */
190 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
192 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
193 /* Free the identifier when update failed */
194 free_parms.dir = aparms.dir;
195 free_parms.type = aparms.type;
196 free_parms.idx = aparms.idx;
197 tf_free_tbl_entry(tfp, &free_parms);
203 /* Retrieve the global template table */
205 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
209 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
210 return ulp_glb_template_tbl;
214 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
220 t_idx = parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
221 BNXT_ULP_GLB_FIELD_TBL_SHIFT);
222 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
223 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
226 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
227 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
228 parms->class_tid, t_idx, operand);
230 return -EINVAL; /* error */
232 *val = ulp_glb_field_tbl[t_idx];
237 * Get the size of the action property for a given index.
239 * idx [in] The index for the action property
241 * returns the size of the action property.
244 ulp_mapper_act_prop_size_get(uint32_t idx)
246 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
248 return ulp_act_prop_map_table[idx];
251 static struct bnxt_ulp_mapper_cond_info *
252 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
255 enum bnxt_ulp_cond_list_opc *opc)
258 const struct bnxt_ulp_template_device_tbls *dev_tbls;
260 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
261 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
262 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
263 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
265 return &dev_tbls->cond_list[idx];
268 static struct bnxt_ulp_mapper_cond_info *
269 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
270 struct bnxt_ulp_mapper_tbl_info *tbl,
272 enum bnxt_ulp_cond_list_opc *opc)
275 const struct bnxt_ulp_template_device_tbls *dev_tbls;
277 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
278 *num_tbls = tbl->execute_info.cond_nums;
279 *opc = tbl->execute_info.cond_list_opcode;
280 idx = tbl->execute_info.cond_start_idx;
282 return &dev_tbls->cond_list[idx];
286 * Get a list of classifier tables that implement the flow
287 * Gets a device dependent list of tables that implement the class template id
289 * mparms [in] The mappers parms with data related to the flow.
291 * tid [in] The template id that matches the flow
293 * num_tbls [out] The number of classifier tables in the returned array
295 * returns An array of classifier tables to implement the flow, or NULL on
298 static struct bnxt_ulp_mapper_tbl_info *
299 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
304 const struct bnxt_ulp_template_device_tbls *dev_tbls;
306 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
308 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
309 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
311 return &dev_tbls->tbl_list[idx];
315 * Get the list of key fields that implement the flow.
317 * mparms [in] The mapper parms with information about the flow
319 * tbl [in] A single table instance to get the key fields from
321 * num_flds [out] The number of key fields in the returned array
323 * Returns array of Key fields, or NULL on error.
325 static struct bnxt_ulp_mapper_key_info *
326 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
327 struct bnxt_ulp_mapper_tbl_info *tbl,
331 const struct bnxt_ulp_template_device_tbls *dev_tbls;
333 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
334 if (!dev_tbls->key_info_list) {
339 idx = tbl->key_start_idx;
340 *num_flds = tbl->key_num_fields;
342 return &dev_tbls->key_info_list[idx];
346 * Get the list of data fields that implement the flow.
348 * mparms [in] The mapper parms with information about the flow
350 * tbl [in] A single table instance to get the data fields from
352 * num_flds [out] The number of data fields in the returned array.
354 * num_encap_flds [out] The number of encap fields in the returned array.
356 * Returns array of data fields, or NULL on error.
358 static struct bnxt_ulp_mapper_field_info *
359 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
360 struct bnxt_ulp_mapper_tbl_info *tbl,
362 uint32_t *num_encap_flds)
365 const struct bnxt_ulp_template_device_tbls *dev_tbls;
367 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
368 if (!dev_tbls->result_field_list) {
374 idx = tbl->result_start_idx;
375 *num_flds = tbl->result_num_fields;
376 *num_encap_flds = tbl->encap_num_fields;
378 return &dev_tbls->result_field_list[idx];
382 * Get the list of ident fields that implement the flow
384 * tbl [in] A single table instance to get the ident fields from
386 * num_flds [out] The number of ident fields in the returned array
388 * returns array of ident fields, or NULL on error
390 static struct bnxt_ulp_mapper_ident_info *
391 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
392 struct bnxt_ulp_mapper_tbl_info *tbl,
396 const struct bnxt_ulp_template_device_tbls *dev_tbls;
398 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
399 if (!dev_tbls->ident_list) {
404 idx = tbl->ident_start_idx;
405 *num_flds = tbl->ident_nums;
407 return &dev_tbls->ident_list[idx];
410 static inline int32_t
411 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
413 struct ulp_flow_db_res_params *res)
415 struct tf_free_tcam_entry_parms fparms = {
416 .dir = res->direction,
417 .tcam_tbl_type = res->resource_type,
418 .idx = (uint16_t)res->resource_hndl
421 return tf_free_tcam_entry(tfp, &fparms);
424 static inline int32_t
425 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
427 struct ulp_flow_db_res_params *res)
429 struct tf_free_tbl_entry_parms fparms = {
430 .dir = res->direction,
431 .type = res->resource_type,
432 .idx = (uint32_t)res->resource_hndl
436 * Just get the table scope, it will be ignored if not necessary
437 * by the tf_free_tbl_entry
439 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
441 return tf_free_tbl_entry(tfp, &fparms);
444 static inline int32_t
445 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
447 struct ulp_flow_db_res_params *res)
449 struct tf_delete_em_entry_parms fparms = { 0 };
452 fparms.dir = res->direction;
453 if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)
454 fparms.mem = TF_MEM_EXTERNAL;
456 fparms.mem = TF_MEM_INTERNAL;
457 fparms.flow_handle = res->resource_hndl;
459 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
461 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
465 return tf_delete_em_entry(tfp, &fparms);
468 static inline int32_t
469 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
471 struct ulp_flow_db_res_params *res)
473 struct tf_free_identifier_parms fparms = {
474 .dir = res->direction,
475 .ident_type = res->resource_type,
476 .id = (uint16_t)res->resource_hndl
479 return tf_free_identifier(tfp, &fparms);
482 static inline int32_t
483 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
484 struct ulp_flow_db_res_params *res)
486 return ulp_mark_db_mark_del(ulp,
491 static inline int32_t
492 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
494 struct ulp_flow_db_res_params *res)
496 uint32_t idx, child_fid = 0, parent_idx;
497 struct bnxt_ulp_flow_db *flow_db;
499 parent_idx = (uint32_t)res->resource_hndl;
501 /* check the validity of the parent fid */
502 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
504 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
508 /* Clear all the child flows parent index */
509 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
510 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
512 /* update the child flows resource handle */
513 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
515 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
521 /* free the parent entry in the parent table flow */
522 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
523 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
529 static inline int32_t
530 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
532 struct ulp_flow_db_res_params *res)
536 parent_fid = (uint32_t)res->resource_hndl;
538 return 0; /* Already freed - orphan child*/
540 /* reset the child flow bitset*/
541 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
542 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
543 parent_fid, child_fid);
550 * Process the flow database opcode alloc action.
551 * returns 0 on success
554 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
555 struct bnxt_ulp_mapper_tbl_info *tbl)
561 /* allocate a new fid */
562 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
563 BNXT_ULP_FDB_TYPE_RID,
567 "Unable to allocate flow table entry\n");
570 /* Store the allocated fid in regfile*/
572 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
573 tfp_cpu_to_be_64(val64));
575 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
577 ulp_flow_db_fid_free(parms->ulp_ctx,
578 BNXT_ULP_FDB_TYPE_RID, rid);
585 * Process the flow database opcode action.
586 * returns 0 on success.
589 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
590 struct bnxt_ulp_mapper_tbl_info *tbl,
591 struct ulp_flow_db_res_params *fid_parms)
595 enum bnxt_ulp_fdb_type flow_type;
598 switch (tbl->fdb_opcode) {
599 case BNXT_ULP_FDB_OPC_PUSH_FID:
600 push_fid = parms->fid;
601 flow_type = parms->flow_type;
603 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
604 /* get the fid from the regfile */
605 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
608 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
612 /* Use the extracted fid to update the flow resource */
613 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
614 flow_type = BNXT_ULP_FDB_TYPE_RID;
617 return rc; /* Nothing to be done */
620 /* Add the resource to the flow database */
621 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
622 push_fid, fid_parms);
624 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
630 * Process the flow database opcode action.
631 * returns 0 on success.
634 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
635 struct bnxt_ulp_mapper_tbl_info *tbl,
640 switch (tbl->pri_opcode) {
641 case BNXT_ULP_PRI_OPC_NOT_USED:
644 case BNXT_ULP_PRI_OPC_CONST:
645 *priority = tbl->pri_operand;
647 case BNXT_ULP_PRI_OPC_APP_PRI:
648 *priority = parms->app_priority;
651 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
660 * Process the identifier list in the given table.
661 * Extract the ident from the table entry and
662 * write it to the reg file.
663 * returns 0 on success.
666 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
667 struct bnxt_ulp_mapper_tbl_info *tbl,
669 uint32_t byte_data_size,
670 enum bnxt_ulp_byte_order byte_order)
672 struct bnxt_ulp_mapper_ident_info *idents;
673 uint32_t i, num_idents = 0;
676 /* validate the null arguments */
678 BNXT_TF_DBG(ERR, "invalid argument\n");
682 /* Get the ident list and process each one */
683 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
685 for (i = 0; i < num_idents; i++) {
686 /* check the size of the buffer for validation */
687 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
688 ULP_BYTE_2_BITS(byte_data_size) ||
689 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
690 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
691 idents[i].ident_bit_pos,
692 idents[i].ident_bit_size,
697 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
698 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
700 idents[i].ident_bit_pos,
701 idents[i].ident_bit_size);
703 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
704 idents[i].ident_bit_pos,
705 idents[i].ident_bit_size);
707 /* Write it to the regfile, val64 is already in big-endian*/
708 if (ulp_regfile_write(parms->regfile,
709 idents[i].regfile_idx, val64)) {
710 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
711 idents[i].regfile_idx);
719 * Process the identifier instruction and either store it in the flow database
720 * or return it in the val (if not NULL) on success. If val is NULL, the
721 * identifier is to be stored in the flow database.
724 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
725 struct bnxt_ulp_mapper_tbl_info *tbl,
726 struct bnxt_ulp_mapper_ident_info *ident,
729 struct ulp_flow_db_res_params fid_parms;
732 struct tf_alloc_identifier_parms iparms = { 0 };
733 struct tf_free_identifier_parms free_parms = { 0 };
737 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
739 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
743 idx = ident->regfile_idx;
745 iparms.ident_type = ident->ident_type;
746 iparms.dir = tbl->direction;
748 rc = tf_alloc_identifier(tfp, &iparms);
750 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
751 tf_dir_2_str(iparms.dir),
752 tf_ident_2_str(iparms.ident_type));
756 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
757 if (ulp_regfile_write(parms->regfile, idx, id)) {
758 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
760 /* Need to free the identifier, so goto error */
764 /* Link the resource to the flow in the flow db */
766 memset(&fid_parms, 0, sizeof(fid_parms));
767 fid_parms.direction = tbl->direction;
768 fid_parms.resource_func = ident->resource_func;
769 fid_parms.resource_type = ident->ident_type;
770 fid_parms.resource_hndl = iparms.id;
771 fid_parms.critical_resource = tbl->critical_resource;
773 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
775 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
777 /* Need to free the identifier, so goto error */
786 /* Need to free the identifier */
787 free_parms.dir = tbl->direction;
788 free_parms.ident_type = ident->ident_type;
789 free_parms.id = iparms.id;
791 (void)tf_free_identifier(tfp, &free_parms);
793 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
795 tf_dir_2_str(tbl->direction));
800 * Process the identifier instruction and extract it from result blob.
801 * Increment the identifier reference count and store it in the flow database.
804 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
805 struct bnxt_ulp_mapper_tbl_info *tbl,
806 struct bnxt_ulp_mapper_ident_info *ident,
807 struct ulp_blob *res_blob)
809 struct ulp_flow_db_res_params fid_parms;
812 struct tf_search_identifier_parms sparms = { 0 };
813 struct tf_free_identifier_parms free_parms = { 0 };
817 /* Get the tfp from ulp context */
818 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
820 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
824 /* Extract the index from the result blob */
825 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
826 ident->ident_bit_pos, ident->ident_bit_size);
828 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
832 /* populate the search params and search identifier shadow table */
833 sparms.ident_type = ident->ident_type;
834 sparms.dir = tbl->direction;
835 /* convert the idx into cpu format */
836 sparms.search_id = tfp_be_to_cpu_32(idx);
838 /* Search identifier also increase the reference count */
839 rc = tf_search_identifier(tfp, &sparms);
841 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
842 tf_dir_2_str(sparms.dir),
843 tf_ident_2_str(sparms.ident_type),
848 /* Write it to the regfile */
849 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
850 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
851 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
853 /* Need to free the identifier, so goto error */
857 /* Link the resource to the flow in the flow db */
858 memset(&fid_parms, 0, sizeof(fid_parms));
859 fid_parms.direction = tbl->direction;
860 fid_parms.resource_func = ident->resource_func;
861 fid_parms.resource_type = ident->ident_type;
862 fid_parms.resource_hndl = sparms.search_id;
863 fid_parms.critical_resource = tbl->critical_resource;
864 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
866 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
868 /* Need to free the identifier, so goto error */
875 /* Need to free the identifier */
876 free_parms.dir = tbl->direction;
877 free_parms.ident_type = ident->ident_type;
878 free_parms.id = sparms.search_id;
879 (void)tf_free_identifier(tfp, &free_parms);
880 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
882 tf_dir_2_str(tbl->direction), sparms.search_id);
887 ulp_mapper_field_process_inc_dec(struct bnxt_ulp_mapper_field_info *fld,
888 struct ulp_blob *blob,
890 uint16_t const_val16,
892 uint32_t *update_flag)
894 uint64_t l_val64 = *val64;
896 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST ||
897 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
898 l_val64 += const_val16;
899 l_val64 = tfp_be_to_cpu_64(l_val64);
900 ulp_blob_push_64(blob, &l_val64, bitlen);
901 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST ||
902 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST) {
903 l_val64 -= const_val16;
904 l_val64 = tfp_be_to_cpu_64(l_val64);
905 ulp_blob_push_64(blob, &l_val64, bitlen);
907 BNXT_TF_DBG(ERR, "Invalid field opcode %u\n", fld->field_opc);
911 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST ||
912 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
920 ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,
922 struct bnxt_ulp_mapper_field_info *fld,
923 struct ulp_blob *blob,
927 uint32_t val_size = 0, field_size = 0;
928 uint64_t hdr_bit, act_bit, regval;
929 uint16_t write_idx = blob->write_idx;
930 uint16_t idx, size_idx, bitlen, offset;
934 uint32_t src1_sel = 0;
935 enum bnxt_ulp_field_src fld_src;
936 uint8_t *fld_src_oper;
937 enum bnxt_ulp_field_cond_src field_cond_src;
938 uint16_t const_val = 0;
939 uint32_t update_flag = 0;
942 /* process the field opcode */
943 if (fld->field_opc != BNXT_ULP_FIELD_OPC_COND_OP) {
944 field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE;
945 /* Read the constant from the second operand */
946 memcpy(&const_val, fld->field_opr2, sizeof(uint16_t));
947 const_val = tfp_be_to_cpu_16(const_val);
949 field_cond_src = fld->field_cond_src;
952 bitlen = fld->field_bit_size;
953 /* Evaluate the condition */
954 switch (field_cond_src) {
955 case BNXT_ULP_FIELD_COND_SRC_TRUE:
958 case BNXT_ULP_FIELD_COND_SRC_CF:
959 if (!ulp_operand_read(fld->field_cond_opr,
960 (uint8_t *)&idx, sizeof(uint16_t))) {
961 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
964 idx = tfp_be_to_cpu_16(idx);
965 if (idx >= BNXT_ULP_CF_IDX_LAST) {
966 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
969 /* check if the computed field is set */
970 if (ULP_COMP_FLD_IDX_RD(parms, idx))
973 case BNXT_ULP_FIELD_COND_SRC_RF:
974 if (!ulp_operand_read(fld->field_cond_opr,
975 (uint8_t *)&idx, sizeof(uint16_t))) {
976 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
980 idx = tfp_be_to_cpu_16(idx);
981 /* Uninitialized regfile entries return 0 */
982 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
983 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
990 case BNXT_ULP_FIELD_COND_SRC_ACT_BIT:
991 if (!ulp_operand_read(fld->field_cond_opr,
992 (uint8_t *)&act_bit, sizeof(uint64_t))) {
993 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
996 act_bit = tfp_be_to_cpu_64(act_bit);
997 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1000 case BNXT_ULP_FIELD_COND_SRC_HDR_BIT:
1001 if (!ulp_operand_read(fld->field_cond_opr,
1002 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1003 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1006 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1007 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1010 case BNXT_ULP_FIELD_COND_SRC_FIELD_BIT:
1011 if (!ulp_operand_read(fld->field_cond_opr, (uint8_t *)&idx,
1012 sizeof(uint16_t))) {
1013 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1016 idx = tfp_be_to_cpu_16(idx);
1017 /* get the index from the global field list */
1018 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1019 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1023 if (bit && (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)))
1027 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1028 name, fld->field_cond_src, write_idx);
1032 /* pick the selected source */
1034 fld_src = fld->field_src1;
1035 fld_src_oper = fld->field_opr1;
1037 fld_src = fld->field_src2;
1038 fld_src_oper = fld->field_opr2;
1041 /* Perform the action */
1043 case BNXT_ULP_FIELD_SRC_ZERO:
1044 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1045 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1049 case BNXT_ULP_FIELD_SRC_CONST:
1051 if (!ulp_blob_push(blob, val, bitlen)) {
1052 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1056 case BNXT_ULP_FIELD_SRC_ONES:
1057 val = mapper_fld_ones;
1058 if (!ulp_blob_push(blob, val, bitlen)) {
1059 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1063 case BNXT_ULP_FIELD_SRC_CF:
1064 if (!ulp_operand_read(fld_src_oper,
1065 (uint8_t *)&idx, sizeof(uint16_t))) {
1066 BNXT_TF_DBG(ERR, "%s operand read failed.\n",
1070 idx = tfp_be_to_cpu_16(idx);
1071 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1072 BNXT_TF_DBG(ERR, "%s comp field [%d] read oob\n",
1076 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1077 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1080 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1085 src1_val64 = ULP_COMP_FLD_IDX_RD(parms, idx);
1086 if (ulp_mapper_field_process_inc_dec(fld, blob,
1091 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1096 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1102 case BNXT_ULP_FIELD_SRC_RF:
1103 if (!ulp_operand_read(fld_src_oper,
1104 (uint8_t *)&idx, sizeof(uint16_t))) {
1105 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1109 idx = tfp_be_to_cpu_16(idx);
1110 /* Uninitialized regfile entries return 0 */
1111 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1112 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1116 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1117 val = ulp_blob_push_64(blob, ®val, bitlen);
1119 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1124 if (ulp_mapper_field_process_inc_dec(fld, blob,
1129 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1134 regval = tfp_cpu_to_be_64(regval);
1135 if (ulp_regfile_write(parms->regfile, idx,
1138 "Write regfile[%d] fail\n",
1145 case BNXT_ULP_FIELD_SRC_ACT_PROP:
1146 if (!ulp_operand_read(fld_src_oper,
1147 (uint8_t *)&idx, sizeof(uint16_t))) {
1148 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1151 idx = tfp_be_to_cpu_16(idx);
1153 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1154 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1157 val = &parms->act_prop->act_details[idx];
1158 field_size = ulp_mapper_act_prop_size_get(idx);
1159 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1160 field_size = field_size - ((bitlen + 7) / 8);
1163 if (!ulp_blob_push(blob, val, bitlen)) {
1164 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1168 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1169 if (!ulp_operand_read(fld_src_oper,
1170 (uint8_t *)&idx, sizeof(uint16_t))) {
1171 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1174 idx = tfp_be_to_cpu_16(idx);
1176 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1177 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1180 val = &parms->act_prop->act_details[idx];
1182 /* get the size index next */
1183 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1184 (uint8_t *)&size_idx, sizeof(uint16_t))) {
1185 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1188 size_idx = tfp_be_to_cpu_16(size_idx);
1190 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1191 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1194 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1196 val_size = tfp_be_to_cpu_32(val_size);
1197 val_size = ULP_BYTE_2_BITS(val_size);
1198 ulp_blob_push_encap(blob, val, val_size);
1200 case BNXT_ULP_FIELD_SRC_GLB_RF:
1201 if (!ulp_operand_read(fld_src_oper,
1203 sizeof(uint16_t))) {
1204 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1207 idx = tfp_be_to_cpu_16(idx);
1208 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1211 BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n",
1215 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1216 val = ulp_blob_push_64(blob, ®val, bitlen);
1218 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1223 if (ulp_mapper_field_process_inc_dec(fld, blob,
1228 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1233 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1239 case BNXT_ULP_FIELD_SRC_HF:
1240 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1241 sizeof(uint16_t))) {
1242 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1245 idx = tfp_be_to_cpu_16(idx);
1246 /* get the index from the global field list */
1247 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1248 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1253 val = parms->hdr_field[bit].spec;
1255 val = parms->hdr_field[bit].mask;
1258 * Need to account for how much data was pushed to the header
1259 * field vs how much is to be inserted in the key/mask.
1261 field_size = parms->hdr_field[bit].size;
1262 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1263 field_size = field_size - ((bitlen + 7) / 8);
1267 if (!ulp_blob_push(blob, val, bitlen)) {
1268 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1272 case BNXT_ULP_FIELD_SRC_HDR_BIT:
1273 if (!ulp_operand_read(fld_src_oper,
1274 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1275 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1278 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1279 memset(tmpval, 0, sizeof(tmpval));
1280 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1282 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1283 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1286 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1287 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1292 case BNXT_ULP_FIELD_SRC_ACT_BIT:
1293 if (!ulp_operand_read(fld_src_oper,
1294 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1295 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1298 act_bit = tfp_be_to_cpu_64(act_bit);
1299 memset(tmpval, 0, sizeof(tmpval));
1300 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1302 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1303 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1306 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1307 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1312 case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1313 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1314 sizeof(uint16_t))) {
1315 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1318 idx = tfp_be_to_cpu_16(idx);
1319 /* get the index from the global field list */
1320 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1321 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1325 memset(tmpval, 0, sizeof(tmpval));
1326 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))
1328 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1329 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1332 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1333 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1338 case BNXT_ULP_FIELD_SRC_SKIP:
1341 case BNXT_ULP_FIELD_SRC_REJECT:
1343 case BNXT_ULP_FIELD_SRC_SUB_HF:
1344 if (!ulp_operand_read(fld_src_oper,
1345 (uint8_t *)&idx, sizeof(uint16_t))) {
1346 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1349 idx = tfp_be_to_cpu_16(idx);
1350 /* get the index from the global field list */
1351 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1352 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1357 /* get the offset next */
1358 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1359 (uint8_t *)&offset, sizeof(uint16_t))) {
1360 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1363 offset = tfp_be_to_cpu_16(offset);
1364 if ((offset + bitlen) >
1365 ULP_BYTE_2_BITS(parms->hdr_field[bit].size) ||
1366 ULP_BITS_IS_BYTE_NOT_ALIGNED(offset)) {
1367 BNXT_TF_DBG(ERR, "Hdr field[%s] oob\n", name);
1370 offset = ULP_BITS_2_BYTE_NR(offset);
1372 /* write the value into blob */
1374 val = &parms->hdr_field[bit].spec[offset];
1376 val = &parms->hdr_field[bit].mask[offset];
1378 if (!ulp_blob_push(blob, val, bitlen)) {
1379 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1384 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1385 name, fld_src, write_idx);
1392 * Result table process and fill the result blob.
1393 * data [out] - the result blob data
1396 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1397 struct bnxt_ulp_mapper_tbl_info *tbl,
1398 struct ulp_blob *data,
1401 struct bnxt_ulp_mapper_field_info *dflds;
1402 uint32_t i, num_flds = 0, encap_flds = 0;
1405 /* Get the result field list */
1406 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1409 /* validate the result field list counts */
1410 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1411 (!num_flds && !encap_flds)) || !dflds ||
1412 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1413 (!num_flds || encap_flds))) {
1414 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1415 num_flds, encap_flds);
1419 /* process the result fields, loop through them */
1420 for (i = 0; i < (num_flds + encap_flds); i++) {
1421 /* set the swap index if encap swap bit is enabled */
1422 if (parms->device_params->encap_byte_swap && encap_flds &&
1424 ulp_blob_encap_swap_idx_set(data);
1426 /* Process the result fields */
1427 rc = ulp_mapper_field_process(parms, tbl->direction,
1428 &dflds[i], data, 0, name);
1430 BNXT_TF_DBG(ERR, "data field failed\n");
1435 /* if encap bit swap is enabled perform the bit swap */
1436 if (parms->device_params->encap_byte_swap && encap_flds)
1437 ulp_blob_perform_encap_swap(data);
1443 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1444 struct bnxt_ulp_mapper_tbl_info *tbl,
1447 struct ulp_flow_db_res_params fid_parms;
1448 uint32_t mark, gfid, mark_flag;
1449 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1452 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1453 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1454 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1455 BNXT_ULP_ACT_BIT_MARK)))
1456 return rc; /* no need to perform gfid process */
1458 /* Get the mark id details from action property */
1459 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1461 mark = tfp_be_to_cpu_32(mark);
1463 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1464 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1466 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1469 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1472 fid_parms.direction = tbl->direction;
1473 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1474 fid_parms.critical_resource = tbl->critical_resource;
1475 fid_parms.resource_type = mark_flag;
1476 fid_parms.resource_hndl = gfid;
1477 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1479 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1484 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1485 struct bnxt_ulp_mapper_tbl_info *tbl)
1487 struct ulp_flow_db_res_params fid_parms;
1488 uint32_t act_idx, mark, mark_flag;
1490 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1493 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1494 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1495 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1496 BNXT_ULP_ACT_BIT_MARK)))
1497 return rc; /* no need to perform mark action process */
1499 /* Get the mark id details from action property */
1500 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1502 mark = tfp_be_to_cpu_32(mark);
1504 if (!ulp_regfile_read(parms->regfile,
1505 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1507 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1510 act_idx = tfp_be_to_cpu_64(val64);
1511 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1512 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1515 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1518 fid_parms.direction = tbl->direction;
1519 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1520 fid_parms.critical_resource = tbl->critical_resource;
1521 fid_parms.resource_type = mark_flag;
1522 fid_parms.resource_hndl = act_idx;
1523 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1525 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1530 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1531 struct bnxt_ulp_mapper_tbl_info *tbl)
1533 struct ulp_flow_db_res_params fid_parms;
1534 uint32_t act_idx, mark, mark_flag;
1536 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1539 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1540 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1541 return rc; /* no need to perform mark action process */
1543 /* Get the mark id details from the computed field of dev port id */
1544 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1546 /* Get the main action pointer */
1547 if (!ulp_regfile_read(parms->regfile,
1548 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1550 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1553 act_idx = tfp_be_to_cpu_64(val64);
1555 /* Set the mark flag to local fid and vfr flag */
1556 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1558 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1561 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1564 fid_parms.direction = tbl->direction;
1565 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1566 fid_parms.critical_resource = tbl->critical_resource;
1567 fid_parms.resource_type = mark_flag;
1568 fid_parms.resource_hndl = act_idx;
1569 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1571 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1575 /* Tcam table scan the identifier list and allocate each identifier */
1577 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1578 struct bnxt_ulp_mapper_tbl_info *tbl)
1580 struct bnxt_ulp_mapper_ident_info *idents;
1581 uint32_t num_idents;
1584 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1585 for (i = 0; i < num_idents; i++) {
1586 if (ulp_mapper_ident_process(parms, tbl,
1594 * Tcam table scan the identifier list and extract the identifier from
1598 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1599 struct bnxt_ulp_mapper_tbl_info *tbl,
1600 struct ulp_blob *data)
1602 struct bnxt_ulp_mapper_ident_info *idents;
1603 uint32_t num_idents = 0, i;
1607 * Extract the listed identifiers from the result field,
1608 * no need to allocate them.
1610 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1611 for (i = 0; i < num_idents; i++) {
1612 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1614 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1621 /* Internal function to write the tcam entry */
1623 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1624 struct bnxt_ulp_mapper_tbl_info *tbl,
1625 struct ulp_blob *key,
1626 struct ulp_blob *mask,
1627 struct ulp_blob *data,
1630 struct tf_set_tcam_entry_parms sparms = { 0 };
1635 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1637 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1641 sparms.dir = tbl->direction;
1642 sparms.tcam_tbl_type = tbl->resource_type;
1644 /* Already verified the key/mask lengths */
1645 sparms.key = ulp_blob_data_get(key, &tmplen);
1646 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1647 sparms.key_sz_in_bits = tbl->key_bit_size;
1648 sparms.result = ulp_blob_data_get(data, &tmplen);
1650 if (tbl->result_bit_size != tmplen) {
1651 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1652 tmplen, tbl->result_bit_size);
1655 sparms.result_sz_in_bits = tbl->result_bit_size;
1656 if (tf_set_tcam_entry(tfp, &sparms)) {
1657 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1658 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1659 tf_dir_2_str(sparms.dir), sparms.idx);
1664 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1666 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1673 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1674 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1676 ulp_blob_perform_64B_word_swap(blob);
1677 ulp_blob_perform_64B_byte_swap(blob);
1681 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1682 struct bnxt_ulp_mapper_tbl_info *tbl)
1684 struct bnxt_ulp_mapper_key_info *kflds;
1685 struct ulp_blob key, mask, data, update_data;
1686 uint32_t i, num_kflds;
1689 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1690 struct tf_search_tcam_entry_parms searchparms = { 0 };
1691 struct ulp_flow_db_res_params fid_parms = { 0 };
1692 struct tf_free_tcam_entry_parms free_parms = { 0 };
1694 uint16_t tmplen = 0;
1697 /* Skip this if table opcode is NOP */
1698 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1699 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1700 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1705 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1707 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1711 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1712 if (!kflds || !num_kflds) {
1713 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1717 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1718 parms->device_params->byte_order) ||
1719 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1720 parms->device_params->byte_order) ||
1721 !ulp_blob_init(&data, tbl->result_bit_size,
1722 parms->device_params->byte_order) ||
1723 !ulp_blob_init(&update_data, tbl->result_bit_size,
1724 parms->device_params->byte_order)) {
1725 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1729 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1730 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1731 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1734 /* create the key/mask */
1736 * NOTE: The WC table will require some kind of flag to handle the
1737 * mode bits within the key/mask
1739 for (i = 0; i < num_kflds; i++) {
1741 rc = ulp_mapper_field_process(parms, tbl->direction,
1742 &kflds[i].field_info_spec,
1743 &key, 1, "TCAM Key");
1745 BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1746 kflds[i].field_info_spec.description);
1750 /* Setup the mask */
1751 rc = ulp_mapper_field_process(parms, tbl->direction,
1752 &kflds[i].field_info_mask,
1753 &mask, 0, "TCAM Mask");
1755 BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1756 kflds[i].field_info_mask.description);
1761 /* For wild card tcam perform the post process to swap the blob */
1762 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1763 ulp_mapper_wc_tcam_tbl_post_process(&key);
1764 ulp_mapper_wc_tcam_tbl_post_process(&mask);
1767 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1768 /* allocate the tcam index */
1769 aparms.dir = tbl->direction;
1770 aparms.tcam_tbl_type = tbl->resource_type;
1771 aparms.key = ulp_blob_data_get(&key, &tmplen);
1772 aparms.key_sz_in_bits = tmplen;
1773 if (tbl->blob_key_bit_size != tmplen) {
1774 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1775 tmplen, tbl->blob_key_bit_size);
1779 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1780 if (tbl->blob_key_bit_size != tmplen) {
1781 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1782 tmplen, tbl->blob_key_bit_size);
1786 /* calculate the entry priority */
1787 rc = ulp_mapper_priority_opc_process(parms, tbl,
1790 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1794 rc = tf_alloc_tcam_entry(tfp, &aparms);
1796 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1803 * Searching before allocation to see if we already have an
1804 * entry. This allows re-use of a constrained resource.
1806 searchparms.dir = tbl->direction;
1807 searchparms.tcam_tbl_type = tbl->resource_type;
1808 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1809 searchparms.key_sz_in_bits = tbl->key_bit_size;
1810 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1811 searchparms.alloc = 1;
1812 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1813 searchparms.result_sz_in_bits = tbl->result_bit_size;
1815 /* calculate the entry priority */
1816 rc = ulp_mapper_priority_opc_process(parms, tbl,
1817 &searchparms.priority);
1819 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1823 rc = tf_search_tcam_entry(tfp, &searchparms);
1825 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1829 /* Successful search, check the result */
1830 if (searchparms.search_status == REJECT) {
1831 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1834 idx = searchparms.idx;
1835 hit = searchparms.hit;
1838 /* Write the tcam index into the regfile*/
1839 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1840 (uint64_t)tfp_cpu_to_be_64(idx))) {
1841 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1844 /* Need to free the tcam idx, so goto error */
1848 /* if it is miss then it is same as no search before alloc */
1849 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1850 /*Scan identifier list, allocate identifier and update regfile*/
1851 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1852 /* Create the result blob */
1854 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1856 /* write the tcam entry */
1858 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1861 /*Scan identifier list, extract identifier and update regfile*/
1862 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1867 /* Add the tcam index to the flow database */
1868 fid_parms.direction = tbl->direction;
1869 fid_parms.resource_func = tbl->resource_func;
1870 fid_parms.resource_type = tbl->resource_type;
1871 fid_parms.critical_resource = tbl->critical_resource;
1872 fid_parms.resource_hndl = idx;
1873 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1875 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1877 /* Need to free the identifier, so goto error */
1883 free_parms.dir = tbl->direction;
1884 free_parms.tcam_tbl_type = tbl->resource_type;
1885 free_parms.idx = idx;
1886 trc = tf_free_tcam_entry(tfp, &free_parms);
1888 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1889 tbl->resource_type, tbl->direction, idx);
1894 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1895 struct bnxt_ulp_mapper_tbl_info *tbl)
1897 struct bnxt_ulp_mapper_key_info *kflds;
1898 struct ulp_blob key, data;
1899 uint32_t i, num_kflds;
1901 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1902 struct ulp_flow_db_res_params fid_parms = { 0 };
1903 struct tf_insert_em_entry_parms iparms = { 0 };
1904 struct tf_delete_em_entry_parms free_parms = { 0 };
1905 enum bnxt_ulp_flow_mem_type mtype;
1909 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1911 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1915 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1916 if (!kflds || !num_kflds) {
1917 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1921 /* Initialize the key/result blobs */
1922 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1923 parms->device_params->byte_order) ||
1924 !ulp_blob_init(&data, tbl->result_bit_size,
1925 parms->device_params->byte_order)) {
1926 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1930 /* create the key */
1931 for (i = 0; i < num_kflds; i++) {
1933 rc = ulp_mapper_field_process(parms, tbl->direction,
1934 &kflds[i].field_info_spec,
1937 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1943 * TBD: Normally should process identifiers in case of using recycle or
1944 * loopback. Not supporting recycle for now.
1947 /* Create the result data blob */
1948 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1950 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1953 /* do the transpose for the internal EM keys */
1954 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1955 ulp_blob_perform_byte_reverse(&key);
1957 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1958 &iparms.tbl_scope_id);
1960 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1965 * NOTE: the actual blob size will differ from the size in the tbl
1966 * entry due to the padding.
1968 iparms.dup_check = 0;
1969 iparms.dir = tbl->direction;
1970 iparms.mem = tbl->resource_type;
1971 iparms.key = ulp_blob_data_get(&key, &tmplen);
1972 iparms.key_sz_in_bits = tbl->key_bit_size;
1973 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
1974 iparms.em_record_sz_in_bits = tbl->result_bit_size;
1976 rc = tf_insert_em_entry(tfp, &iparms);
1978 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1982 /* Mark action process */
1983 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1984 tbl->resource_type == TF_MEM_EXTERNAL)
1985 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1986 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1987 tbl->resource_type == TF_MEM_INTERNAL)
1988 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1990 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1994 /* Link the EM resource to the flow in the flow db */
1995 memset(&fid_parms, 0, sizeof(fid_parms));
1996 fid_parms.direction = tbl->direction;
1997 fid_parms.resource_func = tbl->resource_func;
1998 fid_parms.resource_type = tbl->resource_type;
1999 fid_parms.critical_resource = tbl->critical_resource;
2000 fid_parms.resource_hndl = iparms.flow_handle;
2002 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2004 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2006 /* Need to free the identifier, so goto error */
2012 free_parms.dir = iparms.dir;
2013 free_parms.mem = iparms.mem;
2014 free_parms.tbl_scope_id = iparms.tbl_scope_id;
2015 free_parms.flow_handle = iparms.flow_handle;
2017 trc = tf_delete_em_entry(tfp, &free_parms);
2019 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2025 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2026 struct bnxt_ulp_mapper_tbl_info *tbl)
2028 struct ulp_flow_db_res_params fid_parms;
2029 struct ulp_blob data;
2030 uint64_t regval = 0;
2032 uint32_t index, hit;
2033 int32_t rc = 0, trc = 0;
2034 struct tf_alloc_tbl_entry_parms aparms = { 0 };
2035 struct tf_search_tbl_entry_parms srchparms = { 0 };
2036 struct tf_set_tbl_entry_parms sparms = { 0 };
2037 struct tf_get_tbl_entry_parms gparms = { 0 };
2038 struct tf_free_tbl_entry_parms free_parms = { 0 };
2039 uint32_t tbl_scope_id;
2040 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2044 bool search = false;
2046 /* use the max size if encap is enabled */
2047 if (tbl->encap_num_fields)
2048 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2050 bit_size = tbl->result_bit_size;
2052 /* Initialize the blob data */
2053 if (!ulp_blob_init(&data, bit_size,
2054 parms->device_params->byte_order)) {
2055 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2059 /* Get the scope id first */
2060 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2062 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2066 switch (tbl->tbl_opcode) {
2067 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2070 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2072 * Build the entry, alloc an index, write the table, and store
2073 * the data in the regfile.
2078 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
2079 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2080 /* Not currently supporting with EXT */
2082 "Ext Table Search Opcode not supported.\n");
2086 * Search for the entry in the tf core. If it is hit, save the
2087 * index in the regfile. If it is a miss, Build the entry,
2088 * alloc an index, write the table, and store the data in the
2089 * regfile (same as ALLOC_WR).
2093 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2095 * get the index to write to from the regfile and then write
2098 if (!ulp_regfile_read(parms->regfile,
2102 "Failed to get tbl idx from regfile[%d].\n",
2106 index = tfp_be_to_cpu_64(regval);
2107 /* For external, we need to reverse shift */
2108 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2109 index = TF_ACT_REC_PTR_2_OFFSET(index);
2113 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2114 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2115 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2119 * get the index to write to from the global regfile and then
2122 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2127 "Failed to get tbl idx from Global "
2132 index = tfp_be_to_cpu_64(regval);
2133 /* For external, we need to reverse shift */
2134 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2135 index = TF_ACT_REC_PTR_2_OFFSET(index);
2138 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2140 * The read is different from the rest and can be handled here
2141 * instead of trying to use common code. Simply read the table
2142 * with the index from the regfile, scan and store the
2143 * identifiers, and return.
2145 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2146 /* Not currently supporting with EXT */
2148 "Ext Table Read Opcode not supported.\n");
2151 if (!ulp_regfile_read(parms->regfile,
2152 tbl->tbl_operand, ®val)) {
2154 "Failed to get tbl idx from regfile[%d]\n",
2158 index = tfp_be_to_cpu_64(regval);
2159 gparms.dir = tbl->direction;
2160 gparms.type = tbl->resource_type;
2161 gparms.data = ulp_blob_data_get(&data, &tmplen);
2162 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2164 rc = tf_get_tbl_entry(tfp, &gparms);
2166 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2167 tbl->resource_type, index);
2171 * Scan the fields in the entry and push them into the regfile.
2173 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2175 gparms.data_sz_in_bytes,
2178 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2184 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2189 if (write || search) {
2190 /* Get the result fields list */
2191 rc = ulp_mapper_tbl_result_build(parms,
2196 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2202 /* Use the result blob to perform a search */
2203 memset(&srchparms, 0, sizeof(srchparms));
2204 srchparms.dir = tbl->direction;
2205 srchparms.type = tbl->resource_type;
2206 srchparms.alloc = 1;
2207 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2208 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2209 srchparms.tbl_scope_id = tbl_scope_id;
2210 rc = tf_search_tbl_entry(tfp, &srchparms);
2212 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2213 tf_tbl_type_2_str(tbl->resource_type),
2214 tf_dir_2_str(tbl->direction), rc);
2217 if (srchparms.search_status == REJECT) {
2218 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2219 tf_tbl_type_2_str(tbl->resource_type),
2220 tf_dir_2_str(tbl->direction));
2223 index = srchparms.idx;
2224 hit = srchparms.hit;
2232 aparms.dir = tbl->direction;
2233 aparms.type = tbl->resource_type;
2234 aparms.tbl_scope_id = tbl_scope_id;
2236 /* All failures after the alloc succeeds require a free */
2237 rc = tf_alloc_tbl_entry(tfp, &aparms);
2239 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2240 tf_tbl_type_2_str(tbl->resource_type),
2241 tf_dir_2_str(tbl->direction), rc);
2247 if (search || alloc) {
2249 * Store the index in the regfile since we either allocated it
2252 * Calculate the idx for the result record, for external EM the
2253 * offset needs to be shifted accordingly.
2254 * If external non-inline table types are used then need to
2255 * revisit this logic.
2257 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2258 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2262 rc = ulp_regfile_write(parms->regfile,
2264 tfp_cpu_to_be_64(regval));
2266 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2267 tbl->tbl_operand, rc);
2273 sparms.dir = tbl->direction;
2274 sparms.type = tbl->resource_type;
2275 sparms.data = ulp_blob_data_get(&data, &tmplen);
2276 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2278 sparms.tbl_scope_id = tbl_scope_id;
2279 rc = tf_set_tbl_entry(tfp, &sparms);
2282 "Index table[%s][%s][%x] write failed "
2284 tf_tbl_type_2_str(sparms.type),
2285 tf_dir_2_str(sparms.dir),
2291 /* Link the resource to the flow in the flow db */
2292 memset(&fid_parms, 0, sizeof(fid_parms));
2293 fid_parms.direction = tbl->direction;
2294 fid_parms.resource_func = tbl->resource_func;
2295 fid_parms.resource_type = tbl->resource_type;
2296 fid_parms.resource_sub_type = tbl->resource_sub_type;
2297 fid_parms.resource_hndl = index;
2298 fid_parms.critical_resource = tbl->critical_resource;
2300 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2302 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2307 /* Perform the VF rep action */
2308 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2310 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2316 * Free the allocated resource since we failed to either
2317 * write to the entry or link the flow
2319 free_parms.dir = tbl->direction;
2320 free_parms.type = tbl->resource_type;
2321 free_parms.idx = index;
2322 free_parms.tbl_scope_id = tbl_scope_id;
2324 trc = tf_free_tbl_entry(tfp, &free_parms);
2326 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2332 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2333 struct bnxt_ulp_mapper_tbl_info *tbl)
2335 struct ulp_blob data, res_blob;
2339 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2340 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2341 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2342 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2345 /* Initialize the blob data */
2346 if (!ulp_blob_init(&data, tbl->result_bit_size,
2347 parms->device_params->byte_order)) {
2348 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2352 /* create the result blob */
2353 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2355 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2359 /* Get the index details */
2361 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2362 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2364 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2365 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2366 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2370 idx = tfp_be_to_cpu_64(idx);
2372 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2373 idx = tbl->tbl_operand;
2375 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2376 /* Initialize the result blob */
2377 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2378 parms->device_params->byte_order)) {
2379 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2383 /* read the interface table */
2384 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2385 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2386 get_parms.dir = tbl->direction;
2387 get_parms.type = tbl->resource_type;
2388 get_parms.idx = idx;
2389 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2390 get_parms.data_sz_in_bytes = res_size;
2392 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2394 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2396 tf_dir_2_str(get_parms.dir),
2400 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2403 res_blob.byte_order);
2405 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2407 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2408 return rc; /* skip it */
2410 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2414 /* Perform the tf table set by filling the set params */
2415 iftbl_params.dir = tbl->direction;
2416 iftbl_params.type = tbl->resource_type;
2417 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2418 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2419 iftbl_params.idx = idx;
2421 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2423 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2424 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2425 tf_dir_2_str(iftbl_params.dir),
2426 iftbl_params.idx, rc);
2431 * TBD: Need to look at the need to store idx in flow db for restore
2432 * the table to its original state on deletion of this entry.
2438 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2439 struct bnxt_ulp_mapper_tbl_info *tbl)
2441 struct bnxt_ulp_mapper_key_info *kflds;
2442 struct ulp_flow_db_res_params fid_parms;
2443 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2445 struct ulp_blob key, data;
2448 uint32_t i, ckey, num_kflds = 0;
2449 uint32_t gen_tbl_hit = 0, fdb_write = 0;
2453 /* Get the key fields list and build the key. */
2454 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2455 if (!kflds || !num_kflds) {
2456 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2459 if (!ulp_blob_init(&key, tbl->key_bit_size,
2460 parms->device_params->byte_order)) {
2461 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2464 for (i = 0; i < num_kflds; i++) {
2466 rc = ulp_mapper_field_process(parms, tbl->direction,
2467 &kflds[i].field_info_spec,
2468 &key, 1, "Gen Tbl Key");
2471 "Failed to create key for Gen tbl rc=%d\n",
2477 /* Calculate the table index for the generic table*/
2478 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2481 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2482 tbl->resource_sub_type, tbl->direction);
2486 /* The_key is a byte array convert it to a search index */
2487 cache_key = ulp_blob_data_get(&key, &tmplen);
2488 memcpy(&ckey, cache_key, sizeof(ckey));
2489 /* Get the generic table entry */
2490 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2491 tbl_idx, ckey, &gen_tbl_ent);
2494 "Failed to create key for Gen tbl rc=%d\n", rc);
2497 switch (tbl->tbl_opcode) {
2498 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2499 /* check the reference count */
2500 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2502 /* Scan ident list and create the result blob*/
2503 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2509 "Failed to scan ident list\n");
2512 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2513 /* increment the reference count */
2514 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2522 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2523 /* check the reference count */
2524 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2525 /* a hit then error */
2526 BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2528 return -EINVAL; /* success */
2531 /* Initialize the blob data */
2532 if (!ulp_blob_init(&data, tbl->result_bit_size,
2533 gen_tbl_ent.byte_order)) {
2534 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2538 /* Get the result fields list */
2539 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2542 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2545 byte_data = ulp_blob_data_get(&data, &tmplen);
2546 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2548 ULP_BITS_2_BYTE(tmplen));
2550 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2554 /* increment the reference count */
2555 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2557 parms->shared_hndl = (uint64_t)tbl_idx << 32 | ckey;
2560 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2564 /* Set the generic entry hit */
2565 rc = ulp_regfile_write(parms->regfile,
2566 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2567 tfp_cpu_to_be_64(gen_tbl_hit));
2569 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2570 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2574 /* add the entry to the flow database */
2576 memset(&fid_parms, 0, sizeof(fid_parms));
2577 fid_parms.direction = tbl->direction;
2578 fid_parms.resource_func = tbl->resource_func;
2579 fid_parms.resource_sub_type = tbl->resource_sub_type;
2580 fid_parms.resource_hndl = ckey;
2581 fid_parms.critical_resource = tbl->critical_resource;
2582 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2584 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2590 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2591 struct bnxt_ulp_mapper_tbl_info *tbl)
2595 /* process the fdb opcode for alloc push */
2596 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2597 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2599 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2607 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2608 struct bnxt_ulp_mapper_data *mapper_data)
2610 struct bnxt_ulp_glb_resource_info *glb_res;
2611 uint32_t num_glb_res_ids, idx;
2614 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2615 if (!glb_res || !num_glb_res_ids) {
2616 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2620 /* Iterate the global resources and process each one */
2621 for (idx = 0; idx < num_glb_res_ids; idx++) {
2622 switch (glb_res[idx].resource_func) {
2623 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2624 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2628 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2629 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2634 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2635 glb_res[idx].resource_func);
2646 * Function to process the memtype opcode of the mapper table.
2647 * returns 1 to skip the table.
2648 * return 0 to continue processing the table.
2653 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2654 struct bnxt_ulp_mapper_tbl_info *tbl)
2656 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2659 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2660 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2664 switch (tbl->mem_type_opcode) {
2665 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT:
2666 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2669 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT:
2670 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2673 case BNXT_ULP_MEM_TYPE_OPC_NOP:
2678 "Invalid arg in mapper in memtype opcode\n");
2685 * Common conditional opcode process routine that is used for both the template
2686 * rejection and table conditional execution.
2689 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2690 enum bnxt_ulp_cond_opc opc,
2699 case BNXT_ULP_COND_OPC_CF_IS_SET:
2700 if (operand < BNXT_ULP_CF_IDX_LAST) {
2701 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2703 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2708 case BNXT_ULP_COND_OPC_CF_NOT_SET:
2709 if (operand < BNXT_ULP_CF_IDX_LAST) {
2710 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2712 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2717 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2718 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2719 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2722 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2727 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2728 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2729 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2732 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2737 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2738 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2739 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2742 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2747 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2748 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2749 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2752 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2757 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2758 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2760 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2764 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2766 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2767 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2769 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2773 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2775 case BNXT_ULP_COND_OPC_RF_IS_SET:
2776 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2777 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2782 case BNXT_ULP_COND_OPC_RF_NOT_SET:
2783 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2784 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2789 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
2790 if (parms->flow_pattern_id == operand) {
2791 BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
2792 parms->flow_pattern_id);
2796 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
2797 if (parms->act_pattern_id == operand) {
2798 BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
2799 parms->act_pattern_id);
2804 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2812 * Processes a list of conditions and returns both a status and result of the
2813 * list. The status must be checked prior to verifying the result.
2815 * returns 0 for success, negative on failure
2816 * returns res = 1 for true, res = 0 for false.
2819 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2820 enum bnxt_ulp_cond_list_opc list_opc,
2821 struct bnxt_ulp_mapper_cond_info *list,
2826 int32_t rc = 0, trc = 0;
2829 case BNXT_ULP_COND_LIST_OPC_AND:
2830 /* AND Defaults to true. */
2833 case BNXT_ULP_COND_LIST_OPC_OR:
2834 /* OR Defaults to false. */
2837 case BNXT_ULP_COND_LIST_OPC_TRUE:
2840 case BNXT_ULP_COND_LIST_OPC_FALSE:
2844 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2849 for (i = 0; i < num; i++) {
2850 rc = ulp_mapper_cond_opc_process(parms,
2851 list[i].cond_opcode,
2852 list[i].cond_operand,
2857 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2858 /* early return if result is ever zero */
2864 /* early return if result is ever non-zero */
2876 * Processes conflict resolution and returns both a status and result.
2877 * The status must be checked prior to verifying the result.
2879 * returns 0 for success, negative on failure
2880 * returns res = 1 for true, res = 0 for false.
2883 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
2884 struct bnxt_ulp_mapper_tbl_info *tbl,
2889 uint64_t comp_sig_id;
2892 switch (tbl->accept_opcode) {
2893 case BNXT_ULP_ACCEPT_OPC_ALWAYS:
2896 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
2897 /* perform the signature validation*/
2898 if (tbl->resource_func ==
2899 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
2900 /* Perform the check that generic table is hit or not */
2901 if (!ulp_regfile_read(parms->regfile,
2902 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2904 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2905 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2909 /* not a hit so no need to check flow sign*/
2914 /* compare the new flow signature against stored one */
2915 if (!ulp_regfile_read(parms->regfile,
2916 BNXT_ULP_RF_IDX_FLOW_SIG_ID,
2918 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2919 BNXT_ULP_RF_IDX_FLOW_SIG_ID);
2922 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
2923 BNXT_ULP_CF_IDX_FLOW_SIG_ID);
2924 regval = tfp_be_to_cpu_64(regval);
2925 if (comp_sig_id == regval)
2928 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
2929 (uint32_t)comp_sig_id, (uint32_t)regval);
2932 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
2933 tbl->accept_opcode);
2940 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2942 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2943 enum bnxt_ulp_cond_list_opc cond_opc;
2944 struct bnxt_ulp_mapper_tbl_info *tbls;
2945 struct bnxt_ulp_mapper_tbl_info *tbl;
2946 uint32_t num_tbls, tbl_idx, num_cond_tbls;
2947 int32_t rc = -EINVAL, cond_rc = 0;
2948 int32_t cond_goto = 1;
2950 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
2954 * Process the reject list if exists, otherwise assume that the
2955 * template is allowed.
2957 if (cond_tbls && num_cond_tbls) {
2958 rc = ulp_mapper_cond_opc_list_process(parms,
2966 /* Reject the template if True */
2968 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
2969 ulp_mapper_tmpl_name_str(parms->tmpl_type),
2975 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2976 if (!tbls || !num_tbls) {
2977 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2978 ulp_mapper_tmpl_name_str(parms->tmpl_type),
2979 parms->dev_id, tid);
2983 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
2984 tbl = &tbls[tbl_idx];
2985 /* Handle the table level opcodes to determine if required. */
2986 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) {
2987 cond_goto = tbl->execute_info.cond_false_goto;
2988 goto next_iteration;
2991 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
2994 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
2995 cond_tbls, num_cond_tbls,
2998 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
3002 /* Skip the table if False */
3004 cond_goto = tbl->execute_info.cond_false_goto;
3005 goto next_iteration;
3008 switch (tbl->resource_func) {
3009 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3010 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3012 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
3013 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
3014 rc = ulp_mapper_em_tbl_process(parms, tbl);
3016 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3017 rc = ulp_mapper_index_tbl_process(parms, tbl);
3019 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3020 rc = ulp_mapper_if_tbl_process(parms, tbl);
3022 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3023 rc = ulp_mapper_gen_tbl_process(parms, tbl);
3025 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3026 rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3028 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3032 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3033 tbl->resource_func);
3039 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3040 tbl->resource_func);
3044 /* perform the post table process */
3045 rc = ulp_mapper_conflict_resolution_process(parms, tbl,
3047 if (rc || !cond_rc) {
3048 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3053 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3054 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3058 tbl_idx += cond_goto;
3063 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3064 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3065 parms->dev_id, tid);
3070 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3072 struct ulp_flow_db_res_params *res)
3078 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3082 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
3084 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3088 switch (res->resource_func) {
3089 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3090 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3092 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
3093 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
3094 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3096 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3097 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3099 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3100 rc = ulp_mapper_ident_free(ulp, tfp, res);
3102 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3103 rc = ulp_mapper_mark_free(ulp, res);
3105 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3106 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3108 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3109 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3111 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3112 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3122 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3123 enum bnxt_ulp_fdb_type flow_type,
3126 struct ulp_flow_db_res_params res_parms = { 0 };
3130 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3135 * Set the critical resource on the first resource del, then iterate
3136 * while status is good
3138 if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3139 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3141 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3145 * This is unexpected on the first call to resource del.
3146 * It likely means that the flow did not exist in the flow db.
3148 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3149 flow_type, fid, rc);
3154 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3157 * On fail, we still need to attempt to free the
3158 * remaining resources. Don't return
3161 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
3162 "] failed rc=%d.\n",
3163 flow_type, fid, res_parms.resource_func,
3164 res_parms.resource_hndl, trc);
3166 /* All subsequent call require the non-critical_resource */
3167 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3169 rc = ulp_flow_db_resource_del(ulp_ctx,
3175 /* Free the Flow ID since we've removed all resources */
3176 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3182 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3183 struct bnxt_ulp_mapper_data *mapper_data)
3185 struct bnxt_ulp_mapper_glb_resource_entry *ent;
3186 struct ulp_flow_db_res_params res;
3189 /* Iterate the global resources and process each one */
3190 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3191 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3193 ent = &mapper_data->glb_res_tbl[dir][idx];
3194 if (ent->resource_func ==
3195 BNXT_ULP_RESOURCE_FUNC_INVALID)
3197 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3198 res.resource_func = ent->resource_func;
3199 res.direction = dir;
3200 res.resource_type = ent->resource_type;
3201 /*convert it from BE to cpu */
3203 tfp_be_to_cpu_64(ent->resource_hndl);
3204 ulp_mapper_resource_free(ulp_ctx, 0, &res);
3210 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3211 enum bnxt_ulp_fdb_type flow_type,
3217 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3221 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3225 /* Function to handle the default global templates that are allocated during
3226 * the startup and reused later.
3229 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
3231 uint32_t *glbl_tmpl_list;
3232 uint32_t num_glb_tmpls, idx, dev_id;
3233 struct bnxt_ulp_mapper_parms parms;
3234 struct bnxt_ulp_mapper_data *mapper_data;
3237 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
3238 if (!glbl_tmpl_list || !num_glb_tmpls)
3239 return rc; /* No global templates to process */
3241 /* Get the device id from the ulp context */
3242 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
3243 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3247 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3249 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3253 /* Iterate the global resources and process each one */
3254 for (idx = 0; idx < num_glb_tmpls; idx++) {
3255 /* Initialize the parms structure */
3256 memset(&parms, 0, sizeof(parms));
3257 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3258 parms.ulp_ctx = ulp_ctx;
3259 parms.dev_id = dev_id;
3260 parms.mapper_data = mapper_data;
3261 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
3262 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3264 /* Get the class table entry from dev id and class id */
3265 parms.class_tid = glbl_tmpl_list[idx];
3267 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3268 if (!parms.device_params) {
3269 BNXT_TF_DBG(ERR, "No device for device id %d\n",
3274 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3281 /* Function to handle the mapping of the Flow to be compatible
3282 * with the underlying hardware.
3285 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3286 struct bnxt_ulp_mapper_create_parms *cparms)
3288 struct bnxt_ulp_mapper_parms parms;
3289 struct ulp_regfile regfile;
3290 int32_t rc = 0, trc;
3292 if (!ulp_ctx || !cparms)
3295 /* Initialize the parms structure */
3296 memset(&parms, 0, sizeof(parms));
3297 parms.act_prop = cparms->act_prop;
3298 parms.act_bitmap = cparms->act;
3299 parms.hdr_bitmap = cparms->hdr_bitmap;
3300 parms.regfile = ®file;
3301 parms.hdr_field = cparms->hdr_field;
3302 parms.fld_bitmap = cparms->fld_bitmap;
3303 parms.comp_fld = cparms->comp_fld;
3304 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3305 parms.ulp_ctx = ulp_ctx;
3306 parms.act_tid = cparms->act_tid;
3307 parms.class_tid = cparms->class_tid;
3308 parms.flow_type = cparms->flow_type;
3309 parms.parent_flow = cparms->parent_flow;
3310 parms.parent_fid = cparms->parent_fid;
3311 parms.fid = cparms->flow_id;
3312 parms.tun_idx = cparms->tun_idx;
3313 parms.app_priority = cparms->app_priority;
3314 parms.flow_pattern_id = cparms->flow_pattern_id;
3315 parms.act_pattern_id = cparms->act_pattern_id;
3317 /* Get the device id from the ulp context */
3318 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3319 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3323 /* Get the device params, it will be used in later processing */
3324 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3325 if (!parms.device_params) {
3326 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3332 * Get the mapper data for dynamic mapper data such as default
3335 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3336 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3337 if (!parms.mapper_data) {
3338 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3342 /* initialize the registry file for further processing */
3343 if (!ulp_regfile_init(parms.regfile)) {
3344 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3348 /* Process the action template list from the selected action table*/
3349 if (parms.act_tid) {
3350 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3351 /* Process the action template tables */
3352 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3357 if (parms.class_tid) {
3358 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3360 /* Process the class template tables.*/
3361 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3366 /* setup the parent-child details */
3367 if (parms.parent_flow) {
3368 /* create a parent flow details */
3369 rc = ulp_flow_db_parent_flow_create(&parms);
3372 } else if (parms.parent_fid) {
3373 /* create a child flow details */
3374 rc = ulp_flow_db_child_flow_create(&parms);
3382 /* Free all resources that were allocated during flow creation */
3383 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3386 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3392 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3394 struct bnxt_ulp_mapper_data *data;
3401 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3405 data = rte_zmalloc("ulp_mapper_data",
3406 sizeof(struct bnxt_ulp_mapper_data), 0);
3408 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3412 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3413 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3414 /* Don't call deinit since the prof_func wasn't allocated. */
3419 /* Allocate the global resource ids */
3420 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3422 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3426 /* Allocate the generic table list */
3427 rc = ulp_mapper_generic_tbl_list_init(data);
3429 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3433 /* Allocate global template table entries */
3434 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3436 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3442 /* Ignore the return code in favor of returning the original error. */
3443 ulp_mapper_deinit(ulp_ctx);
3448 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3450 struct bnxt_ulp_mapper_data *data;
3455 "Failed to acquire ulp context, so data may "
3456 "not be released.\n");
3460 data = (struct bnxt_ulp_mapper_data *)
3461 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3463 /* Go ahead and return since there is no allocated data. */
3464 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3468 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3470 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3471 /* Free the mapper data regardless of errors. */
3472 goto free_mapper_data;
3475 /* Free the global resource info table entries */
3476 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3479 /* Free the generic table */
3480 (void)ulp_mapper_generic_tbl_list_deinit(data);
3483 /* Reset the data pointer within the ulp_ctx. */
3484 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);