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;
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:
1344 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1345 name, fld_src, write_idx);
1352 * Result table process and fill the result blob.
1353 * data [out] - the result blob data
1356 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1357 struct bnxt_ulp_mapper_tbl_info *tbl,
1358 struct ulp_blob *data,
1361 struct bnxt_ulp_mapper_field_info *dflds;
1362 uint32_t i, num_flds = 0, encap_flds = 0;
1365 /* Get the result field list */
1366 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1369 /* validate the result field list counts */
1370 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1371 (!num_flds && !encap_flds)) || !dflds ||
1372 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1373 (!num_flds || encap_flds))) {
1374 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1375 num_flds, encap_flds);
1379 /* process the result fields, loop through them */
1380 for (i = 0; i < (num_flds + encap_flds); i++) {
1381 /* set the swap index if encap swap bit is enabled */
1382 if (parms->device_params->encap_byte_swap && encap_flds &&
1384 ulp_blob_encap_swap_idx_set(data);
1386 /* Process the result fields */
1387 rc = ulp_mapper_field_process(parms, tbl->direction,
1388 &dflds[i], data, 0, name);
1390 BNXT_TF_DBG(ERR, "data field failed\n");
1395 /* if encap bit swap is enabled perform the bit swap */
1396 if (parms->device_params->encap_byte_swap && encap_flds)
1397 ulp_blob_perform_encap_swap(data);
1403 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1404 struct bnxt_ulp_mapper_tbl_info *tbl,
1407 struct ulp_flow_db_res_params fid_parms;
1408 uint32_t mark, gfid, mark_flag;
1409 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1412 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1413 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1414 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1415 BNXT_ULP_ACT_BIT_MARK)))
1416 return rc; /* no need to perform gfid process */
1418 /* Get the mark id details from action property */
1419 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1421 mark = tfp_be_to_cpu_32(mark);
1423 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1424 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1426 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1429 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1432 fid_parms.direction = tbl->direction;
1433 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1434 fid_parms.critical_resource = tbl->critical_resource;
1435 fid_parms.resource_type = mark_flag;
1436 fid_parms.resource_hndl = gfid;
1437 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1439 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1444 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1445 struct bnxt_ulp_mapper_tbl_info *tbl)
1447 struct ulp_flow_db_res_params fid_parms;
1448 uint32_t act_idx, mark, mark_flag;
1450 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1453 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1454 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1455 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1456 BNXT_ULP_ACT_BIT_MARK)))
1457 return rc; /* no need to perform mark action process */
1459 /* Get the mark id details from action property */
1460 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1462 mark = tfp_be_to_cpu_32(mark);
1464 if (!ulp_regfile_read(parms->regfile,
1465 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1467 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1470 act_idx = tfp_be_to_cpu_64(val64);
1471 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1472 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1475 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1478 fid_parms.direction = tbl->direction;
1479 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1480 fid_parms.critical_resource = tbl->critical_resource;
1481 fid_parms.resource_type = mark_flag;
1482 fid_parms.resource_hndl = act_idx;
1483 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1485 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1490 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1491 struct bnxt_ulp_mapper_tbl_info *tbl)
1493 struct ulp_flow_db_res_params fid_parms;
1494 uint32_t act_idx, mark, mark_flag;
1496 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1499 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1500 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1501 return rc; /* no need to perform mark action process */
1503 /* Get the mark id details from the computed field of dev port id */
1504 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1506 /* Get the main action pointer */
1507 if (!ulp_regfile_read(parms->regfile,
1508 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1510 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1513 act_idx = tfp_be_to_cpu_64(val64);
1515 /* Set the mark flag to local fid and vfr flag */
1516 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1518 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1521 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1524 fid_parms.direction = tbl->direction;
1525 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1526 fid_parms.critical_resource = tbl->critical_resource;
1527 fid_parms.resource_type = mark_flag;
1528 fid_parms.resource_hndl = act_idx;
1529 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1531 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1535 /* Tcam table scan the identifier list and allocate each identifier */
1537 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1538 struct bnxt_ulp_mapper_tbl_info *tbl)
1540 struct bnxt_ulp_mapper_ident_info *idents;
1541 uint32_t num_idents;
1544 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1545 for (i = 0; i < num_idents; i++) {
1546 if (ulp_mapper_ident_process(parms, tbl,
1554 * Tcam table scan the identifier list and extract the identifier from
1558 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1559 struct bnxt_ulp_mapper_tbl_info *tbl,
1560 struct ulp_blob *data)
1562 struct bnxt_ulp_mapper_ident_info *idents;
1563 uint32_t num_idents = 0, i;
1567 * Extract the listed identifiers from the result field,
1568 * no need to allocate them.
1570 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1571 for (i = 0; i < num_idents; i++) {
1572 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1574 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1581 /* Internal function to write the tcam entry */
1583 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1584 struct bnxt_ulp_mapper_tbl_info *tbl,
1585 struct ulp_blob *key,
1586 struct ulp_blob *mask,
1587 struct ulp_blob *data,
1590 struct tf_set_tcam_entry_parms sparms = { 0 };
1595 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1597 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1601 sparms.dir = tbl->direction;
1602 sparms.tcam_tbl_type = tbl->resource_type;
1604 /* Already verified the key/mask lengths */
1605 sparms.key = ulp_blob_data_get(key, &tmplen);
1606 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1607 sparms.key_sz_in_bits = tbl->key_bit_size;
1608 sparms.result = ulp_blob_data_get(data, &tmplen);
1610 if (tbl->result_bit_size != tmplen) {
1611 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1612 tmplen, tbl->result_bit_size);
1615 sparms.result_sz_in_bits = tbl->result_bit_size;
1616 if (tf_set_tcam_entry(tfp, &sparms)) {
1617 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1618 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1619 tf_dir_2_str(sparms.dir), sparms.idx);
1624 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1626 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1633 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80
1634 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1635 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob,
1638 uint8_t mode[2] = {0x0, 0x0};
1639 uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE;
1642 /* Add the mode bits to the key and mask*/
1645 else if (mode_len > 2)
1648 size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode));
1649 for (idx = 0; idx < mode_len; idx++)
1650 ulp_blob_insert(blob, (size * idx), mode,
1651 ULP_BYTE_2_BITS(sizeof(mode)));
1652 ulp_blob_perform_64B_word_swap(blob);
1653 ulp_blob_perform_64B_byte_swap(blob);
1657 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1658 struct bnxt_ulp_mapper_tbl_info *tbl)
1660 struct bnxt_ulp_mapper_key_info *kflds;
1661 struct ulp_blob key, mask, data, update_data;
1662 uint32_t i, num_kflds;
1665 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1666 struct tf_search_tcam_entry_parms searchparms = { 0 };
1667 struct ulp_flow_db_res_params fid_parms = { 0 };
1668 struct tf_free_tcam_entry_parms free_parms = { 0 };
1670 uint16_t tmplen = 0;
1673 /* Skip this if table opcode is NOP */
1674 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1675 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1676 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1681 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1683 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1687 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1688 if (!kflds || !num_kflds) {
1689 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1693 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1694 parms->device_params->byte_order) ||
1695 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1696 parms->device_params->byte_order) ||
1697 !ulp_blob_init(&data, tbl->result_bit_size,
1698 parms->device_params->byte_order) ||
1699 !ulp_blob_init(&update_data, tbl->result_bit_size,
1700 parms->device_params->byte_order)) {
1701 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1705 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1706 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1707 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1710 /* create the key/mask */
1712 * NOTE: The WC table will require some kind of flag to handle the
1713 * mode bits within the key/mask
1715 for (i = 0; i < num_kflds; i++) {
1717 rc = ulp_mapper_field_process(parms, tbl->direction,
1718 &kflds[i].field_info_spec,
1719 &key, 1, "TCAM Key");
1721 BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1722 kflds[i].field_info_spec.description);
1726 /* Setup the mask */
1727 rc = ulp_mapper_field_process(parms, tbl->direction,
1728 &kflds[i].field_info_mask,
1729 &mask, 0, "TCAM Mask");
1731 BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1732 kflds[i].field_info_mask.description);
1737 /* For wild card tcam perform the post process to swap the blob */
1738 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1739 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size);
1740 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size);
1743 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1744 /* allocate the tcam index */
1745 aparms.dir = tbl->direction;
1746 aparms.tcam_tbl_type = tbl->resource_type;
1747 aparms.key = ulp_blob_data_get(&key, &tmplen);
1748 aparms.key_sz_in_bits = tmplen;
1749 if (tbl->blob_key_bit_size != tmplen) {
1750 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1751 tmplen, tbl->blob_key_bit_size);
1755 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1756 if (tbl->blob_key_bit_size != tmplen) {
1757 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1758 tmplen, tbl->blob_key_bit_size);
1762 /* calculate the entry priority */
1763 rc = ulp_mapper_priority_opc_process(parms, tbl,
1766 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1770 rc = tf_alloc_tcam_entry(tfp, &aparms);
1772 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1779 * Searching before allocation to see if we already have an
1780 * entry. This allows re-use of a constrained resource.
1782 searchparms.dir = tbl->direction;
1783 searchparms.tcam_tbl_type = tbl->resource_type;
1784 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1785 searchparms.key_sz_in_bits = tbl->key_bit_size;
1786 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1787 searchparms.alloc = 1;
1788 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1789 searchparms.result_sz_in_bits = tbl->result_bit_size;
1791 /* calculate the entry priority */
1792 rc = ulp_mapper_priority_opc_process(parms, tbl,
1793 &searchparms.priority);
1795 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1799 rc = tf_search_tcam_entry(tfp, &searchparms);
1801 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1805 /* Successful search, check the result */
1806 if (searchparms.search_status == REJECT) {
1807 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1810 idx = searchparms.idx;
1811 hit = searchparms.hit;
1814 /* Write the tcam index into the regfile*/
1815 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1816 (uint64_t)tfp_cpu_to_be_64(idx))) {
1817 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1820 /* Need to free the tcam idx, so goto error */
1824 /* if it is miss then it is same as no search before alloc */
1825 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1826 /*Scan identifier list, allocate identifier and update regfile*/
1827 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1828 /* Create the result blob */
1830 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1832 /* write the tcam entry */
1834 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1837 /*Scan identifier list, extract identifier and update regfile*/
1838 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1843 /* Add the tcam index to the flow database */
1844 fid_parms.direction = tbl->direction;
1845 fid_parms.resource_func = tbl->resource_func;
1846 fid_parms.resource_type = tbl->resource_type;
1847 fid_parms.critical_resource = tbl->critical_resource;
1848 fid_parms.resource_hndl = idx;
1849 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1851 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1853 /* Need to free the identifier, so goto error */
1859 free_parms.dir = tbl->direction;
1860 free_parms.tcam_tbl_type = tbl->resource_type;
1861 free_parms.idx = idx;
1862 trc = tf_free_tcam_entry(tfp, &free_parms);
1864 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1865 tbl->resource_type, tbl->direction, idx);
1870 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1871 struct bnxt_ulp_mapper_tbl_info *tbl)
1873 struct bnxt_ulp_mapper_key_info *kflds;
1874 struct ulp_blob key, data;
1875 uint32_t i, num_kflds;
1877 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1878 struct ulp_flow_db_res_params fid_parms = { 0 };
1879 struct tf_insert_em_entry_parms iparms = { 0 };
1880 struct tf_delete_em_entry_parms free_parms = { 0 };
1881 enum bnxt_ulp_flow_mem_type mtype;
1885 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1887 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1891 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1892 if (!kflds || !num_kflds) {
1893 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1897 /* Initialize the key/result blobs */
1898 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1899 parms->device_params->byte_order) ||
1900 !ulp_blob_init(&data, tbl->result_bit_size,
1901 parms->device_params->byte_order)) {
1902 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1906 /* create the key */
1907 for (i = 0; i < num_kflds; i++) {
1909 rc = ulp_mapper_field_process(parms, tbl->direction,
1910 &kflds[i].field_info_spec,
1913 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1919 * TBD: Normally should process identifiers in case of using recycle or
1920 * loopback. Not supporting recycle for now.
1923 /* Create the result data blob */
1924 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1926 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1929 /* do the transpose for the internal EM keys */
1930 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1931 ulp_blob_perform_byte_reverse(&key);
1933 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1934 &iparms.tbl_scope_id);
1936 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1941 * NOTE: the actual blob size will differ from the size in the tbl
1942 * entry due to the padding.
1944 iparms.dup_check = 0;
1945 iparms.dir = tbl->direction;
1946 iparms.mem = tbl->resource_type;
1947 iparms.key = ulp_blob_data_get(&key, &tmplen);
1948 iparms.key_sz_in_bits = tbl->key_bit_size;
1949 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
1950 iparms.em_record_sz_in_bits = tbl->result_bit_size;
1952 rc = tf_insert_em_entry(tfp, &iparms);
1954 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1958 /* Mark action process */
1959 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1960 tbl->resource_type == TF_MEM_EXTERNAL)
1961 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1962 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1963 tbl->resource_type == TF_MEM_INTERNAL)
1964 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1966 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1970 /* Link the EM resource to the flow in the flow db */
1971 memset(&fid_parms, 0, sizeof(fid_parms));
1972 fid_parms.direction = tbl->direction;
1973 fid_parms.resource_func = tbl->resource_func;
1974 fid_parms.resource_type = tbl->resource_type;
1975 fid_parms.critical_resource = tbl->critical_resource;
1976 fid_parms.resource_hndl = iparms.flow_handle;
1978 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1980 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1982 /* Need to free the identifier, so goto error */
1988 free_parms.dir = iparms.dir;
1989 free_parms.mem = iparms.mem;
1990 free_parms.tbl_scope_id = iparms.tbl_scope_id;
1991 free_parms.flow_handle = iparms.flow_handle;
1993 trc = tf_delete_em_entry(tfp, &free_parms);
1995 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2001 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2002 struct bnxt_ulp_mapper_tbl_info *tbl)
2004 struct ulp_flow_db_res_params fid_parms;
2005 struct ulp_blob data;
2006 uint64_t regval = 0;
2008 uint32_t index, hit;
2009 int32_t rc = 0, trc = 0;
2010 struct tf_alloc_tbl_entry_parms aparms = { 0 };
2011 struct tf_search_tbl_entry_parms srchparms = { 0 };
2012 struct tf_set_tbl_entry_parms sparms = { 0 };
2013 struct tf_get_tbl_entry_parms gparms = { 0 };
2014 struct tf_free_tbl_entry_parms free_parms = { 0 };
2015 uint32_t tbl_scope_id;
2016 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2020 bool search = false;
2022 /* use the max size if encap is enabled */
2023 if (tbl->encap_num_fields)
2024 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2026 bit_size = tbl->result_bit_size;
2028 /* Initialize the blob data */
2029 if (!ulp_blob_init(&data, bit_size,
2030 parms->device_params->byte_order)) {
2031 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2035 /* Get the scope id first */
2036 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2038 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2042 switch (tbl->tbl_opcode) {
2043 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2046 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2048 * Build the entry, alloc an index, write the table, and store
2049 * the data in the regfile.
2054 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
2055 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2056 /* Not currently supporting with EXT */
2058 "Ext Table Search Opcode not supported.\n");
2062 * Search for the entry in the tf core. If it is hit, save the
2063 * index in the regfile. If it is a miss, Build the entry,
2064 * alloc an index, write the table, and store the data in the
2065 * regfile (same as ALLOC_WR).
2069 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2071 * get the index to write to from the regfile and then write
2074 if (!ulp_regfile_read(parms->regfile,
2078 "Failed to get tbl idx from regfile[%d].\n",
2082 index = tfp_be_to_cpu_64(regval);
2083 /* For external, we need to reverse shift */
2084 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2085 index = TF_ACT_REC_PTR_2_OFFSET(index);
2089 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2090 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2091 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2095 * get the index to write to from the global regfile and then
2098 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2103 "Failed to get tbl idx from Global "
2108 index = tfp_be_to_cpu_64(regval);
2109 /* For external, we need to reverse shift */
2110 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2111 index = TF_ACT_REC_PTR_2_OFFSET(index);
2114 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2116 * The read is different from the rest and can be handled here
2117 * instead of trying to use common code. Simply read the table
2118 * with the index from the regfile, scan and store the
2119 * identifiers, and return.
2121 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2122 /* Not currently supporting with EXT */
2124 "Ext Table Read Opcode not supported.\n");
2127 if (!ulp_regfile_read(parms->regfile,
2128 tbl->tbl_operand, ®val)) {
2130 "Failed to get tbl idx from regfile[%d]\n",
2134 index = tfp_be_to_cpu_64(regval);
2135 gparms.dir = tbl->direction;
2136 gparms.type = tbl->resource_type;
2137 gparms.data = ulp_blob_data_get(&data, &tmplen);
2138 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2140 rc = tf_get_tbl_entry(tfp, &gparms);
2142 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2143 tbl->resource_type, index);
2147 * Scan the fields in the entry and push them into the regfile.
2149 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2151 gparms.data_sz_in_bytes,
2154 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2160 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2165 if (write || search) {
2166 /* Get the result fields list */
2167 rc = ulp_mapper_tbl_result_build(parms,
2172 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2178 /* Use the result blob to perform a search */
2179 memset(&srchparms, 0, sizeof(srchparms));
2180 srchparms.dir = tbl->direction;
2181 srchparms.type = tbl->resource_type;
2182 srchparms.alloc = 1;
2183 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2184 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2185 srchparms.tbl_scope_id = tbl_scope_id;
2186 rc = tf_search_tbl_entry(tfp, &srchparms);
2188 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2189 tf_tbl_type_2_str(tbl->resource_type),
2190 tf_dir_2_str(tbl->direction), rc);
2193 if (srchparms.search_status == REJECT) {
2194 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2195 tf_tbl_type_2_str(tbl->resource_type),
2196 tf_dir_2_str(tbl->direction));
2199 index = srchparms.idx;
2200 hit = srchparms.hit;
2208 aparms.dir = tbl->direction;
2209 aparms.type = tbl->resource_type;
2210 aparms.tbl_scope_id = tbl_scope_id;
2212 /* All failures after the alloc succeeds require a free */
2213 rc = tf_alloc_tbl_entry(tfp, &aparms);
2215 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2216 tf_tbl_type_2_str(tbl->resource_type),
2217 tf_dir_2_str(tbl->direction), rc);
2223 if (search || alloc) {
2225 * Store the index in the regfile since we either allocated it
2228 * Calculate the idx for the result record, for external EM the
2229 * offset needs to be shifted accordingly.
2230 * If external non-inline table types are used then need to
2231 * revisit this logic.
2233 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2234 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2238 rc = ulp_regfile_write(parms->regfile,
2240 tfp_cpu_to_be_64(regval));
2242 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2243 tbl->tbl_operand, rc);
2249 sparms.dir = tbl->direction;
2250 sparms.type = tbl->resource_type;
2251 sparms.data = ulp_blob_data_get(&data, &tmplen);
2252 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2254 sparms.tbl_scope_id = tbl_scope_id;
2255 rc = tf_set_tbl_entry(tfp, &sparms);
2258 "Index table[%s][%s][%x] write failed "
2260 tf_tbl_type_2_str(sparms.type),
2261 tf_dir_2_str(sparms.dir),
2267 /* Link the resource to the flow in the flow db */
2268 memset(&fid_parms, 0, sizeof(fid_parms));
2269 fid_parms.direction = tbl->direction;
2270 fid_parms.resource_func = tbl->resource_func;
2271 fid_parms.resource_type = tbl->resource_type;
2272 fid_parms.resource_sub_type = tbl->resource_sub_type;
2273 fid_parms.resource_hndl = index;
2274 fid_parms.critical_resource = tbl->critical_resource;
2276 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2278 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2283 /* Perform the VF rep action */
2284 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2286 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2292 * Free the allocated resource since we failed to either
2293 * write to the entry or link the flow
2295 free_parms.dir = tbl->direction;
2296 free_parms.type = tbl->resource_type;
2297 free_parms.idx = index;
2298 free_parms.tbl_scope_id = tbl_scope_id;
2300 trc = tf_free_tbl_entry(tfp, &free_parms);
2302 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2308 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2309 struct bnxt_ulp_mapper_tbl_info *tbl)
2311 struct ulp_blob data, res_blob;
2315 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2316 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2317 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2318 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2321 /* Initialize the blob data */
2322 if (!ulp_blob_init(&data, tbl->result_bit_size,
2323 parms->device_params->byte_order)) {
2324 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2328 /* create the result blob */
2329 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2331 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2335 /* Get the index details */
2337 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2338 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2340 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2341 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2342 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2346 idx = tfp_be_to_cpu_64(idx);
2348 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2349 idx = tbl->tbl_operand;
2351 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2352 /* Initialize the result blob */
2353 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2354 parms->device_params->byte_order)) {
2355 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2359 /* read the interface table */
2360 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2361 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2362 get_parms.dir = tbl->direction;
2363 get_parms.type = tbl->resource_type;
2364 get_parms.idx = idx;
2365 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2366 get_parms.data_sz_in_bytes = res_size;
2368 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2370 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2372 tf_dir_2_str(get_parms.dir),
2376 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2379 res_blob.byte_order);
2381 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2383 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2384 return rc; /* skip it */
2386 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2390 /* Perform the tf table set by filling the set params */
2391 iftbl_params.dir = tbl->direction;
2392 iftbl_params.type = tbl->resource_type;
2393 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2394 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2395 iftbl_params.idx = idx;
2397 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2399 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2400 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2401 tf_dir_2_str(iftbl_params.dir),
2402 iftbl_params.idx, rc);
2407 * TBD: Need to look at the need to store idx in flow db for restore
2408 * the table to its original state on deletion of this entry.
2414 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2415 struct bnxt_ulp_mapper_tbl_info *tbl)
2417 struct bnxt_ulp_mapper_key_info *kflds;
2418 struct ulp_flow_db_res_params fid_parms;
2419 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2421 struct ulp_blob key, data;
2424 uint32_t i, ckey, num_kflds = 0;
2425 uint32_t gen_tbl_hit = 0, fdb_write = 0;
2429 /* Get the key fields list and build the key. */
2430 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2431 if (!kflds || !num_kflds) {
2432 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2435 if (!ulp_blob_init(&key, tbl->key_bit_size,
2436 parms->device_params->byte_order)) {
2437 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2440 for (i = 0; i < num_kflds; i++) {
2442 rc = ulp_mapper_field_process(parms, tbl->direction,
2443 &kflds[i].field_info_spec,
2444 &key, 1, "Gen Tbl Key");
2447 "Failed to create key for Gen tbl rc=%d\n",
2453 /* Calculate the table index for the generic table*/
2454 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2457 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2458 tbl->resource_sub_type, tbl->direction);
2462 /* The_key is a byte array convert it to a search index */
2463 cache_key = ulp_blob_data_get(&key, &tmplen);
2464 memcpy(&ckey, cache_key, sizeof(ckey));
2465 /* Get the generic table entry */
2466 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2467 tbl_idx, ckey, &gen_tbl_ent);
2470 "Failed to create key for Gen tbl rc=%d\n", rc);
2473 switch (tbl->tbl_opcode) {
2474 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2475 /* check the reference count */
2476 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2478 /* Scan ident list and create the result blob*/
2479 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2485 "Failed to scan ident list\n");
2488 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2489 /* increment the reference count */
2490 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2498 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2499 /* check the reference count */
2500 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2501 /* a hit then error */
2502 BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2504 return -EINVAL; /* success */
2507 /* Initialize the blob data */
2508 if (!ulp_blob_init(&data, tbl->result_bit_size,
2509 gen_tbl_ent.byte_order)) {
2510 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2514 /* Get the result fields list */
2515 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2518 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2521 byte_data = ulp_blob_data_get(&data, &tmplen);
2522 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2524 ULP_BITS_2_BYTE(tmplen));
2526 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2530 /* increment the reference count */
2531 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2533 parms->shared_hndl = (uint64_t)tbl_idx << 32 | ckey;
2536 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2540 /* Set the generic entry hit */
2541 rc = ulp_regfile_write(parms->regfile,
2542 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2543 tfp_cpu_to_be_64(gen_tbl_hit));
2545 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2546 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2550 /* add the entry to the flow database */
2552 memset(&fid_parms, 0, sizeof(fid_parms));
2553 fid_parms.direction = tbl->direction;
2554 fid_parms.resource_func = tbl->resource_func;
2555 fid_parms.resource_sub_type = tbl->resource_sub_type;
2556 fid_parms.resource_hndl = ckey;
2557 fid_parms.critical_resource = tbl->critical_resource;
2558 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2560 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2566 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2567 struct bnxt_ulp_mapper_tbl_info *tbl)
2571 /* process the fdb opcode for alloc push */
2572 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2573 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2575 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2583 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2584 struct bnxt_ulp_mapper_data *mapper_data)
2586 struct bnxt_ulp_glb_resource_info *glb_res;
2587 uint32_t num_glb_res_ids, idx;
2590 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2591 if (!glb_res || !num_glb_res_ids) {
2592 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2596 /* Iterate the global resources and process each one */
2597 for (idx = 0; idx < num_glb_res_ids; idx++) {
2598 switch (glb_res[idx].resource_func) {
2599 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2600 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2604 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2605 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2610 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2611 glb_res[idx].resource_func);
2622 * Function to process the memtype opcode of the mapper table.
2623 * returns 1 to skip the table.
2624 * return 0 to continue processing the table.
2629 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2630 struct bnxt_ulp_mapper_tbl_info *tbl)
2632 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2635 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2636 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2640 switch (tbl->mem_type_opcode) {
2641 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT:
2642 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2645 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT:
2646 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2649 case BNXT_ULP_MEM_TYPE_OPC_NOP:
2654 "Invalid arg in mapper in memtype opcode\n");
2661 * Common conditional opcode process routine that is used for both the template
2662 * rejection and table conditional execution.
2665 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2666 enum bnxt_ulp_cond_opc opc,
2675 case BNXT_ULP_COND_OPC_CF_IS_SET:
2676 if (operand < BNXT_ULP_CF_IDX_LAST) {
2677 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2679 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2684 case BNXT_ULP_COND_OPC_CF_NOT_SET:
2685 if (operand < BNXT_ULP_CF_IDX_LAST) {
2686 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2688 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2693 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2694 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2695 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2698 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2703 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2704 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2705 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2708 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2713 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2714 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2715 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2718 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2723 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2724 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2725 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2728 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2733 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2734 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2736 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2740 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2742 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2743 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2745 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2749 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2751 case BNXT_ULP_COND_OPC_RF_IS_SET:
2752 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2753 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2758 case BNXT_ULP_COND_OPC_RF_NOT_SET:
2759 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2760 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2765 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
2766 if (parms->flow_pattern_id == operand) {
2767 BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
2768 parms->flow_pattern_id);
2772 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
2773 if (parms->act_pattern_id == operand) {
2774 BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
2775 parms->act_pattern_id);
2780 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2788 * Processes a list of conditions and returns both a status and result of the
2789 * list. The status must be checked prior to verifying the result.
2791 * returns 0 for success, negative on failure
2792 * returns res = 1 for true, res = 0 for false.
2795 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2796 enum bnxt_ulp_cond_list_opc list_opc,
2797 struct bnxt_ulp_mapper_cond_info *list,
2802 int32_t rc = 0, trc = 0;
2805 case BNXT_ULP_COND_LIST_OPC_AND:
2806 /* AND Defaults to true. */
2809 case BNXT_ULP_COND_LIST_OPC_OR:
2810 /* OR Defaults to false. */
2813 case BNXT_ULP_COND_LIST_OPC_TRUE:
2816 case BNXT_ULP_COND_LIST_OPC_FALSE:
2820 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2825 for (i = 0; i < num; i++) {
2826 rc = ulp_mapper_cond_opc_process(parms,
2827 list[i].cond_opcode,
2828 list[i].cond_operand,
2833 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2834 /* early return if result is ever zero */
2840 /* early return if result is ever non-zero */
2852 * Processes conflict resolution and returns both a status and result.
2853 * The status must be checked prior to verifying the result.
2855 * returns 0 for success, negative on failure
2856 * returns res = 1 for true, res = 0 for false.
2859 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
2860 struct bnxt_ulp_mapper_tbl_info *tbl,
2865 uint64_t comp_sig_id;
2868 switch (tbl->accept_opcode) {
2869 case BNXT_ULP_ACCEPT_OPC_ALWAYS:
2872 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
2873 /* perform the signature validation*/
2874 if (tbl->resource_func ==
2875 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
2876 /* Perform the check that generic table is hit or not */
2877 if (!ulp_regfile_read(parms->regfile,
2878 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2880 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2881 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2885 /* not a hit so no need to check flow sign*/
2890 /* compare the new flow signature against stored one */
2891 if (!ulp_regfile_read(parms->regfile,
2892 BNXT_ULP_RF_IDX_FLOW_SIG_ID,
2894 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2895 BNXT_ULP_RF_IDX_FLOW_SIG_ID);
2898 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
2899 BNXT_ULP_CF_IDX_FLOW_SIG_ID);
2900 regval = tfp_be_to_cpu_64(regval);
2901 if (comp_sig_id == regval)
2904 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
2905 (uint32_t)comp_sig_id, (uint32_t)regval);
2908 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
2909 tbl->accept_opcode);
2916 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2918 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2919 enum bnxt_ulp_cond_list_opc cond_opc;
2920 struct bnxt_ulp_mapper_tbl_info *tbls;
2921 struct bnxt_ulp_mapper_tbl_info *tbl;
2922 uint32_t num_tbls, tbl_idx, num_cond_tbls;
2923 int32_t rc = -EINVAL, cond_rc = 0;
2924 int32_t cond_goto = 1;
2926 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
2930 * Process the reject list if exists, otherwise assume that the
2931 * template is allowed.
2933 if (cond_tbls && num_cond_tbls) {
2934 rc = ulp_mapper_cond_opc_list_process(parms,
2942 /* Reject the template if True */
2944 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
2945 ulp_mapper_tmpl_name_str(parms->tmpl_type),
2951 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2952 if (!tbls || !num_tbls) {
2953 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2954 ulp_mapper_tmpl_name_str(parms->tmpl_type),
2955 parms->dev_id, tid);
2959 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
2960 tbl = &tbls[tbl_idx];
2961 /* Handle the table level opcodes to determine if required. */
2962 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) {
2963 cond_goto = tbl->execute_info.cond_false_goto;
2964 goto next_iteration;
2967 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
2970 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
2971 cond_tbls, num_cond_tbls,
2974 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
2978 /* Skip the table if False */
2980 cond_goto = tbl->execute_info.cond_false_goto;
2981 goto next_iteration;
2984 switch (tbl->resource_func) {
2985 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2986 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2988 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2989 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2990 rc = ulp_mapper_em_tbl_process(parms, tbl);
2992 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2993 rc = ulp_mapper_index_tbl_process(parms, tbl);
2995 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2996 rc = ulp_mapper_if_tbl_process(parms, tbl);
2998 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2999 rc = ulp_mapper_gen_tbl_process(parms, tbl);
3001 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3002 rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3004 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3008 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3009 tbl->resource_func);
3015 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3016 tbl->resource_func);
3020 /* perform the post table process */
3021 rc = ulp_mapper_conflict_resolution_process(parms, tbl,
3023 if (rc || !cond_rc) {
3024 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3029 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3030 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3034 tbl_idx += cond_goto;
3039 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3040 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3041 parms->dev_id, tid);
3046 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3048 struct ulp_flow_db_res_params *res)
3054 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3058 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
3060 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3064 switch (res->resource_func) {
3065 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3066 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3068 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
3069 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
3070 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3072 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3073 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3075 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3076 rc = ulp_mapper_ident_free(ulp, tfp, res);
3078 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3079 rc = ulp_mapper_mark_free(ulp, res);
3081 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3082 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3084 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3085 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3087 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3088 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3098 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3099 enum bnxt_ulp_fdb_type flow_type,
3102 struct ulp_flow_db_res_params res_parms = { 0 };
3106 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3111 * Set the critical resource on the first resource del, then iterate
3112 * while status is good
3114 if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3115 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3117 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3121 * This is unexpected on the first call to resource del.
3122 * It likely means that the flow did not exist in the flow db.
3124 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3125 flow_type, fid, rc);
3130 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3133 * On fail, we still need to attempt to free the
3134 * remaining resources. Don't return
3137 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
3138 "] failed rc=%d.\n",
3139 flow_type, fid, res_parms.resource_func,
3140 res_parms.resource_hndl, trc);
3142 /* All subsequent call require the non-critical_resource */
3143 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3145 rc = ulp_flow_db_resource_del(ulp_ctx,
3151 /* Free the Flow ID since we've removed all resources */
3152 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3158 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3159 struct bnxt_ulp_mapper_data *mapper_data)
3161 struct bnxt_ulp_mapper_glb_resource_entry *ent;
3162 struct ulp_flow_db_res_params res;
3165 /* Iterate the global resources and process each one */
3166 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3167 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3169 ent = &mapper_data->glb_res_tbl[dir][idx];
3170 if (ent->resource_func ==
3171 BNXT_ULP_RESOURCE_FUNC_INVALID)
3173 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3174 res.resource_func = ent->resource_func;
3175 res.direction = dir;
3176 res.resource_type = ent->resource_type;
3177 /*convert it from BE to cpu */
3179 tfp_be_to_cpu_64(ent->resource_hndl);
3180 ulp_mapper_resource_free(ulp_ctx, 0, &res);
3186 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3187 enum bnxt_ulp_fdb_type flow_type,
3193 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3197 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3201 /* Function to handle the default global templates that are allocated during
3202 * the startup and reused later.
3205 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
3207 uint32_t *glbl_tmpl_list;
3208 uint32_t num_glb_tmpls, idx, dev_id;
3209 struct bnxt_ulp_mapper_parms parms;
3210 struct bnxt_ulp_mapper_data *mapper_data;
3213 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
3214 if (!glbl_tmpl_list || !num_glb_tmpls)
3215 return rc; /* No global templates to process */
3217 /* Get the device id from the ulp context */
3218 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
3219 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3223 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3225 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3229 /* Iterate the global resources and process each one */
3230 for (idx = 0; idx < num_glb_tmpls; idx++) {
3231 /* Initialize the parms structure */
3232 memset(&parms, 0, sizeof(parms));
3233 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3234 parms.ulp_ctx = ulp_ctx;
3235 parms.dev_id = dev_id;
3236 parms.mapper_data = mapper_data;
3237 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
3238 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3240 /* Get the class table entry from dev id and class id */
3241 parms.class_tid = glbl_tmpl_list[idx];
3243 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3244 if (!parms.device_params) {
3245 BNXT_TF_DBG(ERR, "No device for device id %d\n",
3250 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3257 /* Function to handle the mapping of the Flow to be compatible
3258 * with the underlying hardware.
3261 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3262 struct bnxt_ulp_mapper_create_parms *cparms)
3264 struct bnxt_ulp_mapper_parms parms;
3265 struct ulp_regfile regfile;
3266 int32_t rc = 0, trc;
3268 if (!ulp_ctx || !cparms)
3271 /* Initialize the parms structure */
3272 memset(&parms, 0, sizeof(parms));
3273 parms.act_prop = cparms->act_prop;
3274 parms.act_bitmap = cparms->act;
3275 parms.hdr_bitmap = cparms->hdr_bitmap;
3276 parms.regfile = ®file;
3277 parms.hdr_field = cparms->hdr_field;
3278 parms.fld_bitmap = cparms->fld_bitmap;
3279 parms.comp_fld = cparms->comp_fld;
3280 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3281 parms.ulp_ctx = ulp_ctx;
3282 parms.act_tid = cparms->act_tid;
3283 parms.class_tid = cparms->class_tid;
3284 parms.flow_type = cparms->flow_type;
3285 parms.parent_flow = cparms->parent_flow;
3286 parms.parent_fid = cparms->parent_fid;
3287 parms.fid = cparms->flow_id;
3288 parms.tun_idx = cparms->tun_idx;
3289 parms.app_priority = cparms->app_priority;
3290 parms.flow_pattern_id = cparms->flow_pattern_id;
3291 parms.act_pattern_id = cparms->act_pattern_id;
3293 /* Get the device id from the ulp context */
3294 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3295 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3299 /* Get the device params, it will be used in later processing */
3300 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3301 if (!parms.device_params) {
3302 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3308 * Get the mapper data for dynamic mapper data such as default
3311 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3312 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3313 if (!parms.mapper_data) {
3314 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3318 /* initialize the registry file for further processing */
3319 if (!ulp_regfile_init(parms.regfile)) {
3320 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3324 /* Process the action template list from the selected action table*/
3325 if (parms.act_tid) {
3326 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3327 /* Process the action template tables */
3328 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3333 if (parms.class_tid) {
3334 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3336 /* Process the class template tables.*/
3337 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3342 /* setup the parent-child details */
3343 if (parms.parent_flow) {
3344 /* create a parent flow details */
3345 rc = ulp_flow_db_parent_flow_create(&parms);
3348 } else if (parms.parent_fid) {
3349 /* create a child flow details */
3350 rc = ulp_flow_db_child_flow_create(&parms);
3358 /* Free all resources that were allocated during flow creation */
3359 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3362 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3368 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3370 struct bnxt_ulp_mapper_data *data;
3377 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3381 data = rte_zmalloc("ulp_mapper_data",
3382 sizeof(struct bnxt_ulp_mapper_data), 0);
3384 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3388 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3389 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3390 /* Don't call deinit since the prof_func wasn't allocated. */
3395 /* Allocate the global resource ids */
3396 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3398 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3402 /* Allocate the generic table list */
3403 rc = ulp_mapper_generic_tbl_list_init(data);
3405 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3409 /* Allocate global template table entries */
3410 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3412 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3418 /* Ignore the return code in favor of returning the original error. */
3419 ulp_mapper_deinit(ulp_ctx);
3424 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3426 struct bnxt_ulp_mapper_data *data;
3431 "Failed to acquire ulp context, so data may "
3432 "not be released.\n");
3436 data = (struct bnxt_ulp_mapper_data *)
3437 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3439 /* Go ahead and return since there is no allocated data. */
3440 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3444 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3446 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3447 /* Free the mapper data regardless of errors. */
3448 goto free_mapper_data;
3451 /* Free the global resource info table entries */
3452 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3455 /* Free the generic table */
3456 (void)ulp_mapper_generic_tbl_list_deinit(data);
3459 /* Reset the data pointer within the ulp_ctx. */
3460 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);