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"
21 static struct bnxt_ulp_glb_resource_info *
22 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
26 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
27 return ulp_glb_resource_tbl;
31 * Read the global resource from the mapper global resource list
33 * The regval is always returned in big-endian.
35 * returns 0 on success
38 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
43 if (!mapper_data || !regval ||
44 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
47 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
52 * Write a global resource to the mapper global resource list
54 * The regval value must be in big-endian.
56 * return 0 on success.
59 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
60 struct bnxt_ulp_glb_resource_info *res,
63 struct bnxt_ulp_mapper_glb_resource_entry *ent;
65 /* validate the arguments */
66 if (!data || res->direction >= TF_DIR_MAX ||
67 res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST)
70 /* write to the mapper data */
71 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
72 ent->resource_func = res->resource_func;
73 ent->resource_type = res->resource_type;
74 ent->resource_hndl = regval;
79 * Internal function to allocate identity resource and store it in mapper data.
81 * returns 0 on success
84 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
85 struct bnxt_ulp_mapper_data *mapper_data,
86 struct bnxt_ulp_glb_resource_info *glb_res)
88 struct tf_alloc_identifier_parms iparms = { 0 };
89 struct tf_free_identifier_parms fparms;
94 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
98 iparms.ident_type = glb_res->resource_type;
99 iparms.dir = glb_res->direction;
101 /* Allocate the Identifier using tf api */
102 rc = tf_alloc_identifier(tfp, &iparms);
104 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
105 tf_dir_2_str(iparms.dir),
110 /* entries are stored as big-endian format */
111 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
112 /* write to the mapper global resource */
113 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
115 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
116 /* Free the identifier when update failed */
117 fparms.dir = iparms.dir;
118 fparms.ident_type = iparms.ident_type;
119 fparms.id = iparms.id;
120 tf_free_identifier(tfp, &fparms);
127 * Internal function to allocate index tbl resource and store it in mapper data.
129 * returns 0 on success
132 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
133 struct bnxt_ulp_mapper_data *mapper_data,
134 struct bnxt_ulp_glb_resource_info *glb_res)
136 struct tf_alloc_tbl_entry_parms aparms = { 0 };
137 struct tf_free_tbl_entry_parms free_parms = { 0 };
140 uint32_t tbl_scope_id;
143 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
147 /* Get the scope id */
148 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
150 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
154 aparms.type = glb_res->resource_type;
155 aparms.dir = glb_res->direction;
156 aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
157 aparms.tbl_scope_id = tbl_scope_id;
159 /* Allocate the index tbl using tf api */
160 rc = tf_alloc_tbl_entry(tfp, &aparms);
162 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
163 tf_dir_2_str(aparms.dir), aparms.type);
167 /* entries are stored as big-endian format */
168 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
169 /* write to the mapper global resource */
170 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
172 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
173 /* Free the identifier when update failed */
174 free_parms.dir = aparms.dir;
175 free_parms.type = aparms.type;
176 free_parms.idx = aparms.idx;
177 tf_free_tbl_entry(tfp, &free_parms);
183 /* Retrieve the global template table */
185 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
189 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
190 return ulp_glb_template_tbl;
194 * Get the size of the action property for a given index.
196 * idx [in] The index for the action property
198 * returns the size of the action property.
201 ulp_mapper_act_prop_size_get(uint32_t idx)
203 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
205 return ulp_act_prop_map_table[idx];
209 * Get a list of classifier tables that implement the flow
210 * Gets a device dependent list of tables that implement the class template id
212 * mparms [in] The mappers parms with data related to the flow.
214 * tid [in] The template id that matches the flow
216 * num_tbls [out] The number of classifier tables in the returned array
218 * returns An array of classifier tables to implement the flow, or NULL on
221 static struct bnxt_ulp_mapper_tbl_info *
222 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
227 const struct ulp_template_device_tbls *dev_tbls;
229 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
231 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
232 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
234 return &dev_tbls->tbl_list[idx];
238 * Get the list of key fields that implement the flow.
240 * mparms [in] The mapper parms with information about the flow
242 * tbl [in] A single table instance to get the key fields from
244 * num_flds [out] The number of key fields in the returned array
246 * Returns array of Key fields, or NULL on error.
248 static struct bnxt_ulp_mapper_key_field_info *
249 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
250 struct bnxt_ulp_mapper_tbl_info *tbl,
254 const struct ulp_template_device_tbls *dev_tbls;
256 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
257 if (!dev_tbls->key_field_list) {
262 idx = tbl->key_start_idx;
263 *num_flds = tbl->key_num_fields;
265 return &dev_tbls->key_field_list[idx];
269 * Get the list of data fields that implement the flow.
271 * mparms [in] The mapper parms with information about the flow
273 * tbl [in] A single table instance to get the data fields from
275 * num_flds [out] The number of data fields in the returned array.
277 * num_encap_flds [out] The number of encap fields in the returned array.
279 * Returns array of data fields, or NULL on error.
281 static struct bnxt_ulp_mapper_result_field_info *
282 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
283 struct bnxt_ulp_mapper_tbl_info *tbl,
285 uint32_t *num_encap_flds)
288 const struct ulp_template_device_tbls *dev_tbls;
290 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
291 if (!dev_tbls->result_field_list) {
297 idx = tbl->result_start_idx;
298 *num_flds = tbl->result_num_fields;
299 *num_encap_flds = tbl->encap_num_fields;
301 return &dev_tbls->result_field_list[idx];
305 * Get the list of ident fields that implement the flow
307 * tbl [in] A single table instance to get the ident fields from
309 * num_flds [out] The number of ident fields in the returned array
311 * returns array of ident fields, or NULL on error
313 static struct bnxt_ulp_mapper_ident_info *
314 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
315 struct bnxt_ulp_mapper_tbl_info *tbl,
319 const struct ulp_template_device_tbls *dev_tbls;
321 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
322 if (!dev_tbls->ident_list) {
327 idx = tbl->ident_start_idx;
328 *num_flds = tbl->ident_nums;
330 return &dev_tbls->ident_list[idx];
333 static inline int32_t
334 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
336 struct ulp_flow_db_res_params *res)
338 struct tf_free_tcam_entry_parms fparms = {
339 .dir = res->direction,
340 .tcam_tbl_type = res->resource_type,
341 .idx = (uint16_t)res->resource_hndl
344 return tf_free_tcam_entry(tfp, &fparms);
347 static inline int32_t
348 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
350 struct ulp_flow_db_res_params *res)
352 struct tf_free_tbl_entry_parms fparms = {
353 .dir = res->direction,
354 .type = res->resource_type,
355 .idx = (uint32_t)res->resource_hndl
359 * Just get the table scope, it will be ignored if not necessary
360 * by the tf_free_tbl_entry
362 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
364 return tf_free_tbl_entry(tfp, &fparms);
367 static inline int32_t
368 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
370 struct ulp_flow_db_res_params *res)
372 struct tf_delete_em_entry_parms fparms = { 0 };
375 fparms.dir = res->direction;
376 if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE)
377 fparms.mem = TF_MEM_EXTERNAL;
379 fparms.mem = TF_MEM_INTERNAL;
380 fparms.flow_handle = res->resource_hndl;
382 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
384 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
388 return tf_delete_em_entry(tfp, &fparms);
391 static inline int32_t
392 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
394 struct ulp_flow_db_res_params *res)
396 struct tf_free_identifier_parms fparms = {
397 .dir = res->direction,
398 .ident_type = res->resource_type,
399 .id = (uint16_t)res->resource_hndl
402 return tf_free_identifier(tfp, &fparms);
405 static inline int32_t
406 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
407 struct ulp_flow_db_res_params *res)
409 return ulp_mark_db_mark_del(ulp,
414 static inline int32_t
415 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
417 struct ulp_flow_db_res_params *res)
419 uint32_t idx, child_fid = 0, parent_idx;
420 struct bnxt_ulp_flow_db *flow_db;
422 parent_idx = (uint32_t)res->resource_hndl;
424 /* check the validity of the parent fid */
425 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
427 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
431 /* Clear all the child flows parent index */
432 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
433 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
435 /* update the child flows resource handle */
436 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
438 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
444 /* free the parent entry in the parent table flow */
445 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
446 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
452 static inline int32_t
453 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
455 struct ulp_flow_db_res_params *res)
459 parent_fid = (uint32_t)res->resource_hndl;
461 return 0; /* Already freed - orphan child*/
463 /* reset the child flow bitset*/
464 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
465 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
466 parent_fid, child_fid);
473 * Process the flow database opcode action.
474 * returns 0 on success.
477 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
478 struct bnxt_ulp_mapper_tbl_info *tbl,
479 struct ulp_flow_db_res_params *fid_parms)
481 uint32_t push_fid, fid = 0;
485 switch (tbl->fdb_opcode) {
486 case BNXT_ULP_FDB_OPC_PUSH:
487 push_fid = parms->fid;
489 case BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE:
490 /* allocate a new fid */
491 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
492 BNXT_ULP_FDB_TYPE_REGULAR,
493 tbl->resource_func, &fid);
496 "Unable to allocate flow table entry\n");
499 /* Store the allocated fid in regfile*/
501 rc = ulp_regfile_write(parms->regfile, tbl->flow_db_operand,
504 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
505 tbl->flow_db_operand);
509 /* Use the allocated fid to update the flow resource */
512 case BNXT_ULP_FDB_OPC_PUSH_REGFILE:
513 /* get the fid from the regfile */
514 rc = ulp_regfile_read(parms->regfile, tbl->flow_db_operand,
517 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
518 tbl->flow_db_operand);
521 /* Use the extracted fid to update the flow resource */
522 push_fid = (uint32_t)val64;
525 return rc; /* Nothing to be done */
528 /* Add the resource to the flow database */
529 rc = ulp_flow_db_resource_add(parms->ulp_ctx, parms->flow_type,
530 push_fid, fid_parms);
532 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
539 /* free the allocated fid */
541 ulp_flow_db_fid_free(parms->ulp_ctx,
542 BNXT_ULP_FDB_TYPE_REGULAR, fid);
547 * Process the identifier instruction and either store it in the flow database
548 * or return it in the val (if not NULL) on success. If val is NULL, the
549 * identifier is to be stored in the flow database.
552 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
553 struct bnxt_ulp_mapper_tbl_info *tbl,
554 struct bnxt_ulp_mapper_ident_info *ident,
557 struct ulp_flow_db_res_params fid_parms;
560 struct tf_alloc_identifier_parms iparms = { 0 };
561 struct tf_free_identifier_parms free_parms = { 0 };
565 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
567 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
571 idx = ident->regfile_idx;
573 iparms.ident_type = ident->ident_type;
574 iparms.dir = tbl->direction;
576 rc = tf_alloc_identifier(tfp, &iparms);
578 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
579 tf_dir_2_str(iparms.dir),
580 tf_ident_2_str(iparms.ident_type));
584 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
585 if (!ulp_regfile_write(parms->regfile, idx, id)) {
586 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
588 /* Need to free the identifier, so goto error */
592 /* Link the resource to the flow in the flow db */
594 memset(&fid_parms, 0, sizeof(fid_parms));
595 fid_parms.direction = tbl->direction;
596 fid_parms.resource_func = ident->resource_func;
597 fid_parms.resource_type = ident->ident_type;
598 fid_parms.resource_hndl = iparms.id;
599 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
601 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
603 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
605 /* Need to free the identifier, so goto error */
614 /* Need to free the identifier */
615 free_parms.dir = tbl->direction;
616 free_parms.ident_type = ident->ident_type;
617 free_parms.id = iparms.id;
619 (void)tf_free_identifier(tfp, &free_parms);
621 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
623 tf_dir_2_str(tbl->direction));
628 * Process the identifier instruction and extract it from result blob.
629 * Increment the identifier reference count and store it in the flow database.
632 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
633 struct bnxt_ulp_mapper_tbl_info *tbl,
634 struct bnxt_ulp_mapper_ident_info *ident,
635 struct ulp_blob *res_blob)
637 struct ulp_flow_db_res_params fid_parms;
640 struct tf_search_identifier_parms sparms = { 0 };
641 struct tf_free_identifier_parms free_parms = { 0 };
645 /* Get the tfp from ulp context */
646 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
648 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
652 /* Extract the index from the result blob */
653 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
654 ident->ident_bit_pos, ident->ident_bit_size);
656 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
660 /* populate the search params and search identifier shadow table */
661 sparms.ident_type = ident->ident_type;
662 sparms.dir = tbl->direction;
663 /* convert the idx into cpu format */
664 sparms.search_id = tfp_be_to_cpu_32(idx);
666 /* Search identifier also increase the reference count */
667 rc = tf_search_identifier(tfp, &sparms);
669 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
670 tf_dir_2_str(sparms.dir),
671 tf_ident_2_str(sparms.ident_type),
676 /* Write it to the regfile */
677 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
678 if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
679 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
681 /* Need to free the identifier, so goto error */
685 /* Link the resource to the flow in the flow db */
686 memset(&fid_parms, 0, sizeof(fid_parms));
687 fid_parms.direction = tbl->direction;
688 fid_parms.resource_func = ident->resource_func;
689 fid_parms.resource_type = ident->ident_type;
690 fid_parms.resource_hndl = sparms.search_id;
691 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
692 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
694 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
696 /* Need to free the identifier, so goto error */
703 /* Need to free the identifier */
704 free_parms.dir = tbl->direction;
705 free_parms.ident_type = ident->ident_type;
706 free_parms.id = sparms.search_id;
707 (void)tf_free_identifier(tfp, &free_parms);
708 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
710 tf_dir_2_str(tbl->direction), sparms.search_id);
715 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
717 struct bnxt_ulp_mapper_result_field_info *fld,
718 struct ulp_blob *blob,
721 uint16_t idx, size_idx;
723 uint16_t write_idx = blob->write_idx;
725 uint32_t val_size = 0, field_size = 0;
730 switch (fld->result_opcode) {
731 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
732 val = fld->result_operand;
733 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
734 BNXT_TF_DBG(ERR, "%s failed to add field\n", name);
738 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP:
739 if (!ulp_operand_read(fld->result_operand,
740 (uint8_t *)&idx, sizeof(uint16_t))) {
741 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
744 idx = tfp_be_to_cpu_16(idx);
746 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
747 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
750 val = &parms->act_prop->act_details[idx];
751 field_size = ulp_mapper_act_prop_size_get(idx);
752 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
753 field_size = field_size -
754 ((fld->field_bit_size + 7) / 8);
757 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
758 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
762 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT:
763 if (!ulp_operand_read(fld->result_operand,
764 (uint8_t *)&act_bit, sizeof(uint64_t))) {
765 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
768 act_bit = tfp_be_to_cpu_64(act_bit);
769 memset(act_val, 0, sizeof(act_val));
770 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
772 if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) {
773 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
776 if (!ulp_blob_push(blob, act_val, fld->field_bit_size)) {
777 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
782 case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ:
783 if (!ulp_operand_read(fld->result_operand,
784 (uint8_t *)&idx, sizeof(uint16_t))) {
785 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
788 idx = tfp_be_to_cpu_16(idx);
790 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
791 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
794 val = &parms->act_prop->act_details[idx];
796 /* get the size index next */
797 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
798 (uint8_t *)&size_idx, sizeof(uint16_t))) {
799 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
802 size_idx = tfp_be_to_cpu_16(size_idx);
804 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
805 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
808 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
810 val_size = tfp_be_to_cpu_32(val_size);
811 val_size = ULP_BYTE_2_BITS(val_size);
812 ulp_blob_push_encap(blob, val, val_size);
814 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
815 if (!ulp_operand_read(fld->result_operand,
816 (uint8_t *)&idx, sizeof(uint16_t))) {
817 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
821 idx = tfp_be_to_cpu_16(idx);
822 /* Uninitialized regfile entries return 0 */
823 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
824 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
829 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size);
831 BNXT_TF_DBG(ERR, "%s push field failed\n", name);
835 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
836 if (!ulp_operand_read(fld->result_operand,
839 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
842 idx = tfp_be_to_cpu_16(idx);
843 if (ulp_mapper_glb_resource_read(parms->mapper_data,
846 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
850 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size);
852 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
856 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
857 if (!ulp_operand_read(fld->result_operand,
860 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
863 idx = tfp_be_to_cpu_16(idx);
864 if (idx < BNXT_ULP_CF_IDX_LAST)
865 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
866 fld->field_bit_size);
868 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
872 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
873 if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) {
874 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
879 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST:
880 if (!ulp_operand_read(fld->result_operand,
881 (uint8_t *)&act_bit, sizeof(uint64_t))) {
882 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
885 act_bit = tfp_be_to_cpu_64(act_bit);
886 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
887 /* Action bit is set so consider operand_true */
888 if (!ulp_operand_read(fld->result_operand_true,
891 BNXT_TF_DBG(ERR, "%s operand read failed\n",
895 idx = tfp_be_to_cpu_16(idx);
896 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
897 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n",
901 val = &parms->act_prop->act_details[idx];
902 field_size = ulp_mapper_act_prop_size_get(idx);
903 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
904 field_size = field_size -
905 ((fld->field_bit_size + 7) / 8);
908 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
909 BNXT_TF_DBG(ERR, "%s push field failed\n",
914 /* action bit is not set, use the operand false */
915 val = fld->result_operand_false;
916 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
917 BNXT_TF_DBG(ERR, "%s failed to add field\n",
923 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST:
924 if (!ulp_operand_read(fld->result_operand,
925 (uint8_t *)&act_bit, sizeof(uint64_t))) {
926 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
929 act_bit = tfp_be_to_cpu_64(act_bit);
930 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) {
931 /* Action bit is set so consider operand_true */
932 val = fld->result_operand_true;
934 /* action bit is not set, use the operand false */
935 val = fld->result_operand_false;
937 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
938 BNXT_TF_DBG(ERR, "%s failed to add field\n",
943 case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF:
944 if (!ulp_operand_read(fld->result_operand,
947 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
950 idx = tfp_be_to_cpu_16(idx);
951 if (idx >= BNXT_ULP_CF_IDX_LAST) {
952 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
955 /* check if the computed field is set */
956 if (ULP_COMP_FLD_IDX_RD(parms, idx))
957 val = fld->result_operand_true;
959 val = fld->result_operand_false;
961 /* read the appropriate computed field */
962 if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) {
963 BNXT_TF_DBG(ERR, "%s val operand read failed\n", name);
966 idx = tfp_be_to_cpu_16(idx);
967 if (idx >= BNXT_ULP_CF_IDX_LAST) {
968 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
971 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
972 fld->field_bit_size);
974 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
978 case BNXT_ULP_MAPPER_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST:
979 if (!ulp_operand_read(fld->result_operand,
980 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
981 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
984 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
985 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) {
986 /* Header bit is set so consider operand_true */
987 val = fld->result_operand_true;
989 /* Header bit is not set, use the operand false */
990 val = fld->result_operand_false;
992 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
993 BNXT_TF_DBG(ERR, "%s failed to add field\n",
999 BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x at %d\n",
1000 fld->result_opcode, write_idx);
1006 /* Function to alloc action record and set the table. */
1008 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
1010 struct bnxt_ulp_mapper_key_field_info *f,
1011 struct ulp_blob *blob,
1016 uint16_t idx, bitlen;
1019 struct ulp_regfile *regfile = parms->regfile;
1020 uint8_t *val = NULL;
1021 struct bnxt_ulp_mapper_key_field_info *fld = f;
1022 uint32_t field_size;
1025 operand = fld->spec_operand;
1026 opcode = fld->spec_opcode;
1028 operand = fld->mask_operand;
1029 opcode = fld->mask_opcode;
1032 bitlen = fld->field_bit_size;
1035 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT:
1037 if (!ulp_blob_push(blob, val, bitlen)) {
1038 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1042 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO:
1043 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1044 BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name);
1049 case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD:
1050 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1051 sizeof(uint16_t))) {
1052 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1055 idx = tfp_be_to_cpu_16(idx);
1057 val = parms->hdr_field[idx].spec;
1059 val = parms->hdr_field[idx].mask;
1062 * Need to account for how much data was pushed to the header
1063 * field vs how much is to be inserted in the key/mask.
1065 field_size = parms->hdr_field[idx].size;
1066 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1067 field_size = field_size - ((bitlen + 7) / 8);
1071 if (!ulp_blob_push(blob, val, bitlen)) {
1072 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1076 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD:
1077 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1078 sizeof(uint16_t))) {
1079 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1082 idx = tfp_be_to_cpu_16(idx);
1083 if (idx < BNXT_ULP_CF_IDX_LAST)
1084 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1087 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1091 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE:
1092 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1093 sizeof(uint16_t))) {
1094 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1097 idx = tfp_be_to_cpu_16(idx);
1099 if (!ulp_regfile_read(regfile, idx, &val64)) {
1100 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1105 val = ulp_blob_push_64(blob, &val64, bitlen);
1107 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1111 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE:
1112 if (!ulp_operand_read(operand, (uint8_t *)&idx,
1113 sizeof(uint16_t))) {
1114 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name);
1117 idx = tfp_be_to_cpu_16(idx);
1118 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1121 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n",
1125 val = ulp_blob_push_64(blob, &val64, bitlen);
1127 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name);
1132 BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n",
1140 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1141 struct bnxt_ulp_mapper_tbl_info *tbl,
1144 struct ulp_flow_db_res_params fid_parms;
1145 uint32_t mark, gfid, mark_flag;
1146 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1149 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1150 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1151 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1152 BNXT_ULP_ACTION_BIT_MARK)))
1153 return rc; /* no need to perform gfid process */
1155 /* Get the mark id details from action property */
1156 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1158 mark = tfp_be_to_cpu_32(mark);
1160 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1161 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1163 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1166 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1169 fid_parms.direction = tbl->direction;
1170 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1171 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1172 fid_parms.resource_type = mark_flag;
1173 fid_parms.resource_hndl = gfid;
1174 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1176 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1181 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1182 struct bnxt_ulp_mapper_tbl_info *tbl)
1184 struct ulp_flow_db_res_params fid_parms;
1185 uint32_t act_idx, mark, mark_flag;
1187 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1190 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1191 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION &&
1192 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1193 BNXT_ULP_ACTION_BIT_MARK)))
1194 return rc; /* no need to perform mark action process */
1196 /* Get the mark id details from action property */
1197 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1199 mark = tfp_be_to_cpu_32(mark);
1201 if (!ulp_regfile_read(parms->regfile,
1202 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1204 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1207 act_idx = tfp_be_to_cpu_64(val64);
1208 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1209 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1212 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1215 fid_parms.direction = tbl->direction;
1216 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1217 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1218 fid_parms.resource_type = mark_flag;
1219 fid_parms.resource_hndl = act_idx;
1220 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1222 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1227 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1228 struct bnxt_ulp_mapper_tbl_info *tbl)
1230 struct ulp_flow_db_res_params fid_parms;
1231 uint32_t act_idx, mark, mark_flag;
1233 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode;
1236 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP ||
1237 mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION)
1238 return rc; /* no need to perform mark action process */
1240 /* Get the mark id details from the computed field of dev port id */
1241 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1243 /* Get the main action pointer */
1244 if (!ulp_regfile_read(parms->regfile,
1245 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR,
1247 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1250 act_idx = tfp_be_to_cpu_64(val64);
1252 /* Set the mark flag to local fid and vfr flag */
1253 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1255 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1258 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1261 fid_parms.direction = tbl->direction;
1262 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1263 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1264 fid_parms.resource_type = mark_flag;
1265 fid_parms.resource_hndl = act_idx;
1266 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1268 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1273 * Tcam table - create the result blob.
1274 * data [out] - the result blob data
1277 ulp_mapper_tcam_tbl_result_create(struct bnxt_ulp_mapper_parms *parms,
1278 struct bnxt_ulp_mapper_tbl_info *tbl,
1279 struct ulp_blob *data)
1281 struct bnxt_ulp_mapper_result_field_info *dflds;
1283 uint32_t encap_flds = 0;
1287 /* Create the result data blob */
1288 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_dflds,
1290 if (!dflds || !num_dflds || encap_flds) {
1291 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1295 for (i = 0; i < num_dflds; i++) {
1296 rc = ulp_mapper_result_field_process(parms,
1302 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
1309 /* Tcam table scan the identifier list and allocate each identifier */
1311 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1312 struct bnxt_ulp_mapper_tbl_info *tbl)
1314 struct bnxt_ulp_mapper_ident_info *idents;
1315 uint32_t num_idents;
1319 * Since the cache entry is responsible for allocating
1320 * identifiers when in use, allocate the identifiers only
1321 * during normal processing.
1323 if (parms->tcam_tbl_opc ==
1324 BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1325 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1327 for (i = 0; i < num_idents; i++) {
1328 if (ulp_mapper_ident_process(parms, tbl,
1337 * Tcam table scan the identifier list and extract the identifier from
1341 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1342 struct bnxt_ulp_mapper_tbl_info *tbl,
1343 struct ulp_blob *data)
1345 struct bnxt_ulp_mapper_ident_info *idents;
1346 uint32_t num_idents = 0, i;
1350 * Extract the listed identifiers from the result field,
1351 * no need to allocate them.
1353 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1354 for (i = 0; i < num_idents; i++) {
1355 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1357 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1364 /* Internal function to write the tcam entry */
1366 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1367 struct bnxt_ulp_mapper_tbl_info *tbl,
1368 struct ulp_blob *key,
1369 struct ulp_blob *mask,
1370 struct ulp_blob *data,
1373 struct tf_set_tcam_entry_parms sparms = { 0 };
1378 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1380 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1384 sparms.dir = tbl->direction;
1385 sparms.tcam_tbl_type = tbl->resource_type;
1387 /* Already verified the key/mask lengths */
1388 sparms.key = ulp_blob_data_get(key, &tmplen);
1389 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1390 sparms.key_sz_in_bits = tbl->key_bit_size;
1391 sparms.result = ulp_blob_data_get(data, &tmplen);
1393 if (tbl->result_bit_size != tmplen) {
1394 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1395 tmplen, tbl->result_bit_size);
1398 sparms.result_sz_in_bits = tbl->result_bit_size;
1399 if (tf_set_tcam_entry(tfp, &sparms)) {
1400 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1401 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1402 tf_dir_2_str(sparms.dir), sparms.idx);
1407 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1409 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1416 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80
1417 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1418 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob,
1421 uint8_t mode[2] = {0x0, 0x0};
1422 uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE;
1425 /* Add the mode bits to the key and mask*/
1428 else if (mode_len > 2)
1431 size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode));
1432 for (idx = 0; idx < mode_len; idx++)
1433 ulp_blob_insert(blob, (size * idx), mode,
1434 ULP_BYTE_2_BITS(sizeof(mode)));
1435 ulp_blob_perform_64B_word_swap(blob);
1436 ulp_blob_perform_64B_byte_swap(blob);
1440 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1441 struct bnxt_ulp_mapper_tbl_info *tbl)
1443 struct bnxt_ulp_mapper_key_field_info *kflds;
1444 struct ulp_blob key, mask, data, update_data;
1445 uint32_t i, num_kflds;
1448 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1449 struct tf_search_tcam_entry_parms searchparms = { 0 };
1450 struct ulp_flow_db_res_params fid_parms = { 0 };
1451 struct tf_free_tcam_entry_parms free_parms = { 0 };
1452 enum bnxt_ulp_search_before_alloc search_flag;
1454 uint16_t tmplen = 0;
1457 /* Skip this if was handled by the cache. */
1458 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) {
1459 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1463 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1465 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1469 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1470 if (!kflds || !num_kflds) {
1471 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1475 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1476 parms->device_params->byte_order) ||
1477 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1478 parms->device_params->byte_order) ||
1479 !ulp_blob_init(&data, tbl->result_bit_size,
1480 parms->device_params->byte_order) ||
1481 !ulp_blob_init(&update_data, tbl->result_bit_size,
1482 parms->device_params->byte_order)) {
1483 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1487 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1488 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1489 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1492 /* create the key/mask */
1494 * NOTE: The WC table will require some kind of flag to handle the
1495 * mode bits within the key/mask
1497 for (i = 0; i < num_kflds; i++) {
1499 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1501 &key, 1, "TCAM Key");
1503 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1507 /* Setup the mask */
1508 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1510 &mask, 0, "TCAM Mask");
1512 BNXT_TF_DBG(ERR, "Mask field set failed.\n");
1517 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1518 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size);
1519 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size);
1522 if (tbl->srch_b4_alloc == BNXT_ULP_SEARCH_BEFORE_ALLOC_NO) {
1524 * No search for re-use is requested, so simply allocate the
1527 aparms.dir = tbl->direction;
1528 aparms.tcam_tbl_type = tbl->resource_type;
1529 aparms.search_enable = tbl->srch_b4_alloc;
1530 aparms.key = ulp_blob_data_get(&key, &tmplen);
1531 aparms.key_sz_in_bits = tmplen;
1532 if (tbl->blob_key_bit_size != tmplen) {
1533 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1534 tmplen, tbl->blob_key_bit_size);
1538 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1539 if (tbl->blob_key_bit_size != tmplen) {
1540 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1541 tmplen, tbl->blob_key_bit_size);
1545 aparms.priority = tbl->priority;
1548 * All failures after this succeeds require the entry to be
1549 * freed. cannot return directly on failure, but needs to goto
1552 rc = tf_alloc_tcam_entry(tfp, &aparms);
1554 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1561 * Searching before allocation to see if we already have an
1562 * entry. This allows re-use of a constrained resource.
1564 searchparms.dir = tbl->direction;
1565 searchparms.tcam_tbl_type = tbl->resource_type;
1566 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1567 searchparms.key_sz_in_bits = tbl->key_bit_size;
1568 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1569 searchparms.priority = tbl->priority;
1570 searchparms.alloc = 1;
1571 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1572 searchparms.result_sz_in_bits = tbl->result_bit_size;
1574 rc = tf_search_tcam_entry(tfp, &searchparms);
1576 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1580 /* Successful search, check the result */
1581 if (searchparms.search_status == REJECT) {
1582 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1585 idx = searchparms.idx;
1586 hit = searchparms.hit;
1589 /* if it is miss then it is same as no search before alloc */
1591 search_flag = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO;
1593 search_flag = tbl->srch_b4_alloc;
1595 switch (search_flag) {
1596 case BNXT_ULP_SEARCH_BEFORE_ALLOC_NO:
1597 /*Scan identifier list, allocate identifier and update regfile*/
1598 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1599 /* Create the result blob */
1601 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl,
1603 /* write the tcam entry */
1605 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1608 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_SKIP:
1609 /*Scan identifier list, extract identifier and update regfile*/
1610 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1612 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_UPDATE:
1613 /*Scan identifier list, extract identifier and update regfile*/
1614 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1615 /* Create the result blob */
1617 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl,
1619 /* Update/overwrite the tcam entry */
1621 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1626 BNXT_TF_DBG(ERR, "invalid search opcode\n");
1633 * Only link the entry to the flow db in the event that cache was not
1636 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) {
1637 fid_parms.direction = tbl->direction;
1638 fid_parms.resource_func = tbl->resource_func;
1639 fid_parms.resource_type = tbl->resource_type;
1640 fid_parms.critical_resource = tbl->critical_resource;
1641 fid_parms.resource_hndl = idx;
1642 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1645 "Failed to link resource to flow rc = %d\n",
1647 /* Need to free the identifier, so goto error */
1652 * Reset the tcam table opcode to normal in case the next tcam
1653 * entry does not use cache.
1655 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1660 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
1661 free_parms.dir = tbl->direction;
1662 free_parms.tcam_tbl_type = tbl->resource_type;
1663 free_parms.idx = idx;
1664 trc = tf_free_tcam_entry(tfp, &free_parms);
1666 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1667 tbl->resource_type, tbl->direction, idx);
1673 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1674 struct bnxt_ulp_mapper_tbl_info *tbl)
1676 struct bnxt_ulp_mapper_key_field_info *kflds;
1677 struct bnxt_ulp_mapper_result_field_info *dflds;
1678 struct ulp_blob key, data;
1679 uint32_t i, num_kflds, num_dflds;
1681 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1682 struct ulp_flow_db_res_params fid_parms = { 0 };
1683 struct tf_insert_em_entry_parms iparms = { 0 };
1684 struct tf_delete_em_entry_parms free_parms = { 0 };
1685 enum bnxt_ulp_flow_mem_type mtype;
1688 uint32_t encap_flds = 0;
1690 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1692 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1696 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1697 if (!kflds || !num_kflds) {
1698 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1702 /* Initialize the key/result blobs */
1703 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1704 parms->device_params->byte_order) ||
1705 !ulp_blob_init(&data, tbl->result_bit_size,
1706 parms->device_params->byte_order)) {
1707 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1711 /* create the key */
1712 for (i = 0; i < num_kflds; i++) {
1714 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
1718 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1724 * TBD: Normally should process identifiers in case of using recycle or
1725 * loopback. Not supporting recycle for now.
1728 /* Create the result data blob */
1729 dflds = ulp_mapper_result_fields_get(parms, tbl,
1730 &num_dflds, &encap_flds);
1731 if (!dflds || !num_dflds || encap_flds) {
1732 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
1736 for (i = 0; i < num_dflds; i++) {
1737 struct bnxt_ulp_mapper_result_field_info *fld;
1741 rc = ulp_mapper_result_field_process(parms,
1747 BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
1751 /* do the transpose for the internal EM keys */
1752 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1753 ulp_blob_perform_byte_reverse(&key);
1755 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1756 &iparms.tbl_scope_id);
1758 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1763 * NOTE: the actual blob size will differ from the size in the tbl
1764 * entry due to the padding.
1766 iparms.dup_check = 0;
1767 iparms.dir = tbl->direction;
1768 iparms.mem = tbl->resource_type;
1769 iparms.key = ulp_blob_data_get(&key, &tmplen);
1770 iparms.key_sz_in_bits = tbl->key_bit_size;
1771 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
1772 iparms.em_record_sz_in_bits = tbl->result_bit_size;
1774 rc = tf_insert_em_entry(tfp, &iparms);
1776 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
1780 /* Mark action process */
1781 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
1782 tbl->resource_type == TF_MEM_EXTERNAL)
1783 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
1784 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
1785 tbl->resource_type == TF_MEM_INTERNAL)
1786 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1788 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1792 /* Link the EM resource to the flow in the flow db */
1793 memset(&fid_parms, 0, sizeof(fid_parms));
1794 fid_parms.direction = tbl->direction;
1795 fid_parms.resource_func = tbl->resource_func;
1796 fid_parms.resource_type = tbl->resource_type;
1797 fid_parms.critical_resource = tbl->critical_resource;
1798 fid_parms.resource_hndl = iparms.flow_handle;
1800 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1802 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
1804 /* Need to free the identifier, so goto error */
1810 free_parms.dir = iparms.dir;
1811 free_parms.mem = iparms.mem;
1812 free_parms.tbl_scope_id = iparms.tbl_scope_id;
1813 free_parms.flow_handle = iparms.flow_handle;
1815 trc = tf_delete_em_entry(tfp, &free_parms);
1817 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
1823 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1824 struct bnxt_ulp_mapper_tbl_info *tbl)
1826 struct bnxt_ulp_mapper_result_field_info *flds;
1827 struct ulp_flow_db_res_params fid_parms;
1828 struct ulp_blob data;
1831 uint32_t i, num_flds, index, hit;
1832 int32_t rc = 0, trc = 0;
1833 struct tf_alloc_tbl_entry_parms aparms = { 0 };
1834 struct tf_search_tbl_entry_parms srchparms = { 0 };
1835 struct tf_set_tbl_entry_parms sparms = { 0 };
1836 struct tf_free_tbl_entry_parms free_parms = { 0 };
1837 uint32_t tbl_scope_id;
1838 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1840 uint32_t encap_flds = 0;
1842 /* Get the scope id first */
1843 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
1845 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
1849 /* use the max size if encap is enabled */
1850 if (tbl->encap_num_fields)
1851 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
1853 bit_size = tbl->result_bit_size;
1855 /* Initialize the blob data */
1856 if (!ulp_blob_init(&data, bit_size,
1857 parms->device_params->byte_order)) {
1858 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
1862 /* Get the result fields list */
1863 flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds);
1865 if (!flds || (!num_flds && !encap_flds)) {
1866 BNXT_TF_DBG(ERR, "template undefined for the index table\n");
1870 /* process the result fields, loop through them */
1871 for (i = 0; i < (num_flds + encap_flds); i++) {
1872 /* set the swap index if encap swap bit is enabled */
1873 if (parms->device_params->encap_byte_swap && encap_flds &&
1875 ulp_blob_encap_swap_idx_set(&data);
1877 /* Process the result fields */
1878 rc = ulp_mapper_result_field_process(parms,
1884 BNXT_TF_DBG(ERR, "data field failed\n");
1889 /* if encap bit swap is enabled perform the bit swap */
1890 if (parms->device_params->encap_byte_swap && encap_flds) {
1891 ulp_blob_perform_encap_swap(&data);
1895 * Check for index opcode, if it is Global then
1896 * no need to allocate the table, just set the table
1897 * and exit since it is not maintained in the flow db.
1899 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) {
1900 /* get the index from index operand */
1901 if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST &&
1902 ulp_mapper_glb_resource_read(parms->mapper_data,
1906 BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n",
1907 tbl->index_operand);
1910 /* set the Tf index table */
1911 sparms.dir = tbl->direction;
1912 sparms.type = tbl->resource_type;
1913 sparms.data = ulp_blob_data_get(&data, &tmplen);
1914 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1915 sparms.idx = tfp_be_to_cpu_64(idx);
1916 sparms.tbl_scope_id = tbl_scope_id;
1918 rc = tf_set_tbl_entry(tfp, &sparms);
1921 "Glbl Index table[%s][%s][%x] failed rc=%d\n",
1922 tf_tbl_type_2_str(sparms.type),
1923 tf_dir_2_str(sparms.dir),
1927 return 0; /* success */
1932 /* Perform the tf table allocation by filling the alloc params */
1933 if (tbl->srch_b4_alloc) {
1934 memset(&srchparms, 0, sizeof(srchparms));
1935 srchparms.dir = tbl->direction;
1936 srchparms.type = tbl->resource_type;
1937 srchparms.alloc = 1;
1938 srchparms.result = ulp_blob_data_get(&data, &tmplen);
1939 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1940 srchparms.tbl_scope_id = tbl_scope_id;
1941 rc = tf_search_tbl_entry(tfp, &srchparms);
1943 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
1944 tf_tbl_type_2_str(tbl->resource_type),
1945 tf_dir_2_str(tbl->direction), rc);
1948 if (srchparms.search_status == REJECT) {
1949 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
1950 tf_tbl_type_2_str(tbl->resource_type),
1951 tf_dir_2_str(tbl->direction));
1954 index = srchparms.idx;
1955 hit = srchparms.hit;
1957 aparms.dir = tbl->direction;
1958 aparms.type = tbl->resource_type;
1959 aparms.search_enable = tbl->srch_b4_alloc;
1960 aparms.result = ulp_blob_data_get(&data, &tmplen);
1961 aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
1962 aparms.tbl_scope_id = tbl_scope_id;
1964 /* All failures after the alloc succeeds require a free */
1965 rc = tf_alloc_tbl_entry(tfp, &aparms);
1967 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
1968 tf_tbl_type_2_str(tbl->resource_type),
1969 tf_dir_2_str(tbl->direction), rc);
1976 * calculate the idx for the result record, for external EM the offset
1977 * needs to be shifted accordingly. If external non-inline table types
1978 * are used then need to revisit this logic.
1980 if (tbl->resource_type == TF_TBL_TYPE_EXT)
1981 idx = TF_ACT_REC_OFFSET_2_PTR(index);
1985 /* Always storing values in Regfile in BE */
1986 idx = tfp_cpu_to_be_64(idx);
1987 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) {
1988 rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx);
1990 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1991 tbl->index_operand);
1996 /* Perform the tf table set by filling the set params */
1997 if (!tbl->srch_b4_alloc || !hit) {
1998 sparms.dir = tbl->direction;
1999 sparms.type = tbl->resource_type;
2000 sparms.data = ulp_blob_data_get(&data, &tmplen);
2001 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2003 sparms.tbl_scope_id = tbl_scope_id;
2005 rc = tf_set_tbl_entry(tfp, &sparms);
2007 BNXT_TF_DBG(ERR, "Set table[%s][%s][%x] failed rc=%d\n",
2008 tf_tbl_type_2_str(sparms.type),
2009 tf_dir_2_str(sparms.dir),
2015 /* Link the resource to the flow in the flow db */
2016 memset(&fid_parms, 0, sizeof(fid_parms));
2017 fid_parms.direction = tbl->direction;
2018 fid_parms.resource_func = tbl->resource_func;
2019 fid_parms.resource_type = tbl->resource_type;
2020 fid_parms.resource_sub_type = tbl->resource_sub_type;
2021 fid_parms.resource_hndl = index;
2022 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2024 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2026 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2031 /* Perform the VF rep action */
2032 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2034 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2040 * Free the allocated resource since we failed to either
2041 * write to the entry or link the flow
2043 free_parms.dir = tbl->direction;
2044 free_parms.type = tbl->resource_type;
2045 free_parms.idx = index;
2046 free_parms.tbl_scope_id = tbl_scope_id;
2048 trc = tf_free_tbl_entry(tfp, &free_parms);
2050 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2056 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2057 struct bnxt_ulp_mapper_tbl_info *tbl)
2059 struct bnxt_ulp_mapper_result_field_info *flds;
2060 struct ulp_blob data;
2063 uint32_t i, num_flds;
2065 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2066 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2067 uint32_t encap_flds;
2069 /* Initialize the blob data */
2070 if (!ulp_blob_init(&data, tbl->result_bit_size,
2071 parms->device_params->byte_order)) {
2072 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2076 /* Get the result fields list */
2077 flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds);
2079 if (!flds || !num_flds || encap_flds) {
2080 BNXT_TF_DBG(ERR, "template undefined for the IF table\n");
2084 /* process the result fields, loop through them */
2085 for (i = 0; i < num_flds; i++) {
2086 /* Process the result fields */
2087 rc = ulp_mapper_result_field_process(parms,
2093 BNXT_TF_DBG(ERR, "data field failed\n");
2098 /* Get the index details from computed field */
2099 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) {
2100 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand);
2101 } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) {
2102 idx = tbl->index_operand;
2104 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2108 /* Perform the tf table set by filling the set params */
2109 iftbl_params.dir = tbl->direction;
2110 iftbl_params.type = tbl->resource_type;
2111 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2112 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2113 iftbl_params.idx = idx;
2115 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2117 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2118 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2119 tf_dir_2_str(iftbl_params.dir),
2120 iftbl_params.idx, rc);
2125 * TBD: Need to look at the need to store idx in flow db for restore
2126 * the table to its original state on deletion of this entry.
2132 * Process the identifier list in the generic table.
2133 * Extract the ident from the generic table entry and
2134 * write it to the reg file.
2137 ulp_mapper_gen_tbl_ident_scan(struct bnxt_ulp_mapper_parms *parms,
2138 struct bnxt_ulp_mapper_tbl_info *tbl,
2139 struct ulp_mapper_gen_tbl_entry *gen_tbl_ent)
2141 struct bnxt_ulp_mapper_ident_info *idents;
2142 uint32_t i, idx, num_idents = 0;
2145 /* Get the ident list */
2146 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
2148 for (i = 0; i < num_idents; i++) {
2149 /* Extract the index from the result byte data array */
2150 rc = ulp_mapper_gen_tbl_entry_data_get(gen_tbl_ent,
2151 idents[i].ident_bit_pos,
2152 idents[i].ident_bit_size,
2156 /* validate the extraction */
2158 BNXT_TF_DBG(ERR, "failed to read %s:%x:%x\n",
2159 idents[i].description,
2160 idents[i].ident_bit_pos,
2161 idents[i].ident_bit_size);
2165 /* Write it to the regfile */
2166 if (!ulp_regfile_write(parms->regfile,
2167 idents[i].regfile_idx, idx)) {
2168 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2169 idents[i].regfile_idx);
2177 * Process the identifier list in the generic table.
2178 * Write the ident to the generic table entry
2181 ulp_mapper_gen_tbl_ident_write(struct bnxt_ulp_mapper_parms *parms,
2182 struct bnxt_ulp_mapper_tbl_info *tbl,
2183 struct ulp_mapper_gen_tbl_entry *gen_tbl_ent)
2185 struct bnxt_ulp_mapper_ident_info *idents;
2186 uint32_t i, num_idents = 0;
2189 /* Get the ident list */
2190 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
2192 for (i = 0; i < num_idents; i++) {
2193 /* read from the regfile */
2194 if (!ulp_regfile_read(parms->regfile, idents[i].regfile_idx,
2196 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2197 idents[i].regfile_idx);
2201 /* Update the gen tbl entry with the new data */
2202 ulp_mapper_gen_tbl_entry_data_set(gen_tbl_ent,
2203 idents[i].ident_bit_pos,
2204 idents[i].ident_bit_size,
2211 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2212 struct bnxt_ulp_mapper_tbl_info *tbl)
2214 struct bnxt_ulp_mapper_key_field_info *kflds;
2215 struct ulp_flow_db_res_params fid_parms;
2216 struct ulp_mapper_gen_tbl_entry gen_tbl_ent;
2218 struct ulp_blob key;
2221 uint32_t i, ckey, num_kflds = 0;
2222 uint32_t gen_tbl_hit = 0, fdb_write = 0;
2225 /* Get the key fields list and build the key. */
2226 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2227 if (!kflds || !num_kflds) {
2228 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2231 if (!ulp_blob_init(&key, tbl->key_bit_size,
2232 parms->device_params->byte_order)) {
2233 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2236 for (i = 0; i < num_kflds; i++) {
2238 rc = ulp_mapper_keymask_field_process(parms, tbl->direction,
2240 &key, 1, "Gen Tbl Key");
2243 "Failed to create key for Gen tbl rc=%d\n",
2249 /* Calculate the table index for the generic table*/
2250 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2253 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2254 tbl->resource_sub_type, tbl->direction);
2258 /* The_key is a byte array convert it to a search index */
2259 cache_key = ulp_blob_data_get(&key, &tmplen);
2260 memcpy(&ckey, cache_key, sizeof(ckey));
2261 /* Get the generic table entry */
2262 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2263 tbl_idx, ckey, &gen_tbl_ent);
2266 "Failed to create key for Gen tbl rc=%d\n", rc);
2269 switch (tbl->tbl_opcode) {
2270 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2271 /* check the reference count */
2272 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2273 /* Scan ident list and create the result blob*/
2274 rc = ulp_mapper_gen_tbl_ident_scan(parms, tbl,
2278 "Failed to scan ident list\n");
2281 /* increment the reference count */
2282 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2289 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2290 /* check the reference count */
2291 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2292 /* a hit then error */
2293 BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2295 return -EINVAL; /* success */
2298 /* Create the result blob from the ident list */
2299 rc = ulp_mapper_gen_tbl_ident_write(parms, tbl, &gen_tbl_ent);
2302 "Failed to write ident list\n");
2306 /* increment the reference count */
2307 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2311 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2315 /* Set the generic entry hit */
2316 rc = ulp_regfile_write(parms->regfile,
2317 BNXT_ULP_REGFILE_INDEX_GENERIC_TBL_HIT,
2320 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2321 tbl->index_operand);
2325 /* add the entry to the flow database */
2327 memset(&fid_parms, 0, sizeof(fid_parms));
2328 fid_parms.direction = tbl->direction;
2329 fid_parms.resource_func = tbl->resource_func;
2330 fid_parms.resource_sub_type = tbl->resource_sub_type;
2331 fid_parms.resource_hndl = ckey;
2332 fid_parms.critical_resource = tbl->critical_resource;
2333 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2335 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2341 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2342 struct bnxt_ulp_mapper_data *mapper_data)
2344 struct bnxt_ulp_glb_resource_info *glb_res;
2345 uint32_t num_glb_res_ids, idx;
2348 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2349 if (!glb_res || !num_glb_res_ids) {
2350 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2354 /* Iterate the global resources and process each one */
2355 for (idx = 0; idx < num_glb_res_ids; idx++) {
2356 switch (glb_res[idx].resource_func) {
2357 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2358 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2362 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2363 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2368 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2369 glb_res[idx].resource_func);
2380 * Function to process the conditional opcode of the mapper table.
2381 * returns 1 to skip the table.
2382 * return 0 to continue processing the table.
2387 ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2388 struct bnxt_ulp_mapper_tbl_info *tbl)
2392 switch (tbl->cond_opcode) {
2393 case BNXT_ULP_COND_OPCODE_NOP:
2396 case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET:
2397 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
2398 ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
2401 case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET:
2402 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2406 case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET:
2407 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2411 case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET:
2412 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST &&
2413 !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand))
2416 case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET:
2417 if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2421 case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET:
2422 if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2428 "Invalid arg in mapper tbl for cond opcode\n");
2435 * Function to process the memtype opcode of the mapper table.
2436 * returns 1 to skip the table.
2437 * return 0 to continue processing the table.
2442 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2443 struct bnxt_ulp_mapper_tbl_info *tbl)
2445 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2448 bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2450 switch (tbl->mem_type_opcode) {
2451 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_INT:
2452 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2455 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_EXT:
2456 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2459 case BNXT_ULP_MEM_TYPE_OPCODE_NOP:
2464 "Invalid arg in mapper in memtype opcode\n");
2471 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2473 struct bnxt_ulp_mapper_tbl_info *tbls;
2474 uint32_t num_tbls, i;
2475 int32_t rc = -EINVAL;
2477 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
2478 if (!tbls || !num_tbls) {
2479 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
2480 (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2481 "class" : "action", parms->dev_id, tid);
2485 for (i = 0; i < num_tbls; i++) {
2486 struct bnxt_ulp_mapper_tbl_info *tbl = &tbls[i];
2488 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl))
2490 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl))
2493 switch (tbl->resource_func) {
2494 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2495 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
2497 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2498 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2499 rc = ulp_mapper_em_tbl_process(parms, tbl);
2501 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2502 rc = ulp_mapper_index_tbl_process(parms, tbl);
2504 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
2505 rc = ulp_mapper_if_tbl_process(parms, tbl);
2507 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2508 rc = ulp_mapper_gen_tbl_process(parms, tbl);
2510 case BNXT_ULP_RESOURCE_FUNC_INVALID:
2514 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
2515 tbl->resource_func);
2521 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
2522 tbl->resource_func);
2529 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
2530 (parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS) ?
2531 "class" : "action", parms->dev_id, tid);
2536 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
2538 struct ulp_flow_db_res_params *res)
2544 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
2548 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
2550 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
2554 switch (res->resource_func) {
2555 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
2556 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
2558 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE:
2559 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE:
2560 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
2562 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2563 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
2565 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2566 rc = ulp_mapper_ident_free(ulp, tfp, res);
2568 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
2569 rc = ulp_mapper_mark_free(ulp, res);
2571 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
2572 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
2574 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
2575 rc = ulp_mapper_child_flow_free(ulp, fid, res);
2577 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
2578 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
2588 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
2589 enum bnxt_ulp_fdb_type flow_type,
2592 struct ulp_flow_db_res_params res_parms = { 0 };
2596 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2601 * Set the critical resource on the first resource del, then iterate
2602 * while status is good
2604 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
2605 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
2609 * This is unexpected on the first call to resource del.
2610 * It likely means that the flow did not exist in the flow db.
2612 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
2613 flow_type, fid, rc);
2618 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
2621 * On fail, we still need to attempt to free the
2622 * remaining resources. Don't return
2625 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
2626 "] failed rc=%d.\n",
2627 flow_type, fid, res_parms.resource_func,
2628 res_parms.resource_hndl, trc);
2630 /* All subsequent call require the non-critical_resource */
2631 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
2633 rc = ulp_flow_db_resource_del(ulp_ctx,
2639 /* Free the Flow ID since we've removed all resources */
2640 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
2646 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
2647 struct bnxt_ulp_mapper_data *mapper_data)
2649 struct bnxt_ulp_mapper_glb_resource_entry *ent;
2650 struct ulp_flow_db_res_params res;
2653 /* Iterate the global resources and process each one */
2654 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
2655 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
2657 ent = &mapper_data->glb_res_tbl[dir][idx];
2658 if (ent->resource_func ==
2659 BNXT_ULP_RESOURCE_FUNC_INVALID)
2661 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
2662 res.resource_func = ent->resource_func;
2663 res.direction = dir;
2664 res.resource_type = ent->resource_type;
2665 /*convert it from BE to cpu */
2667 tfp_be_to_cpu_64(ent->resource_hndl);
2668 ulp_mapper_resource_free(ulp_ctx, 0, &res);
2674 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
2675 enum bnxt_ulp_fdb_type flow_type,
2681 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
2685 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
2689 /* Function to handle the default global templates that are allocated during
2690 * the startup and reused later.
2693 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
2695 uint32_t *glbl_tmpl_list;
2696 uint32_t num_glb_tmpls, idx, dev_id;
2697 struct bnxt_ulp_mapper_parms parms;
2698 struct bnxt_ulp_mapper_data *mapper_data;
2701 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
2702 if (!glbl_tmpl_list || !num_glb_tmpls)
2703 return rc; /* No global templates to process */
2705 /* Get the device id from the ulp context */
2706 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
2707 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2711 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2713 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2717 /* Iterate the global resources and process each one */
2718 for (idx = 0; idx < num_glb_tmpls; idx++) {
2719 /* Initialize the parms structure */
2720 memset(&parms, 0, sizeof(parms));
2721 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2722 parms.ulp_ctx = ulp_ctx;
2723 parms.dev_id = dev_id;
2724 parms.mapper_data = mapper_data;
2725 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
2726 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2728 /* Get the class table entry from dev id and class id */
2729 parms.class_tid = glbl_tmpl_list[idx];
2731 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2732 if (!parms.device_params) {
2733 BNXT_TF_DBG(ERR, "No device for device id %d\n",
2738 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
2745 /* Function to handle the mapping of the Flow to be compatible
2746 * with the underlying hardware.
2749 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
2750 struct bnxt_ulp_mapper_create_parms *cparms)
2752 struct bnxt_ulp_mapper_parms parms;
2753 struct ulp_regfile regfile;
2756 if (!ulp_ctx || !cparms)
2759 /* Initialize the parms structure */
2760 memset(&parms, 0, sizeof(parms));
2761 parms.act_prop = cparms->act_prop;
2762 parms.act_bitmap = cparms->act;
2763 parms.hdr_bitmap = cparms->hdr_bitmap;
2764 parms.regfile = ®file;
2765 parms.hdr_field = cparms->hdr_field;
2766 parms.comp_fld = cparms->comp_fld;
2767 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2768 parms.ulp_ctx = ulp_ctx;
2769 parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL;
2770 parms.act_tid = cparms->act_tid;
2771 parms.class_tid = cparms->class_tid;
2772 parms.flow_type = cparms->flow_type;
2773 parms.parent_flow = cparms->parent_flow;
2774 parms.parent_fid = cparms->parent_fid;
2775 parms.fid = cparms->flow_id;
2776 parms.tun_idx = cparms->tun_idx;
2778 /* Get the device id from the ulp context */
2779 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
2780 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
2784 /* Get the device params, it will be used in later processing */
2785 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
2786 if (!parms.device_params) {
2787 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
2793 * Get the mapper data for dynamic mapper data such as default
2796 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
2797 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2798 if (!parms.mapper_data) {
2799 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
2803 /* initialize the registry file for further processing */
2804 if (!ulp_regfile_init(parms.regfile)) {
2805 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
2809 rc = ulp_regfile_write(parms.regfile,
2810 BNXT_ULP_REGFILE_INDEX_CLASS_TID,
2811 tfp_cpu_to_be_64((uint64_t)parms.class_tid));
2813 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n");
2817 /* Process the action template list from the selected action table*/
2818 if (parms.act_tid) {
2819 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
2820 /* Process the action template tables */
2821 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
2826 if (parms.class_tid) {
2827 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
2829 /* Process the class template tables.*/
2830 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
2835 /* setup the parent-child details */
2836 if (parms.parent_flow) {
2837 /* create a parent flow details */
2838 rc = ulp_flow_db_parent_flow_create(&parms);
2841 } else if (parms.parent_fid) {
2842 /* create a child flow details */
2843 rc = ulp_flow_db_child_flow_create(&parms);
2851 /* Free all resources that were allocated during flow creation */
2852 trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
2855 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
2861 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
2863 struct bnxt_ulp_mapper_data *data;
2870 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2874 data = rte_zmalloc("ulp_mapper_data",
2875 sizeof(struct bnxt_ulp_mapper_data), 0);
2877 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
2881 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
2882 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
2883 /* Don't call deinit since the prof_func wasn't allocated. */
2888 /* Allocate the global resource ids */
2889 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
2891 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
2895 /* Allocate the generic table list */
2896 rc = ulp_mapper_generic_tbl_list_init(data);
2898 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
2902 /* Allocate global template table entries */
2903 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
2905 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
2911 /* Ignore the return code in favor of returning the original error. */
2912 ulp_mapper_deinit(ulp_ctx);
2917 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
2919 struct bnxt_ulp_mapper_data *data;
2924 "Failed to acquire ulp context, so data may "
2925 "not be released.\n");
2929 data = (struct bnxt_ulp_mapper_data *)
2930 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
2932 /* Go ahead and return since there is no allocated data. */
2933 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
2937 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
2939 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
2940 /* Free the mapper data regardless of errors. */
2941 goto free_mapper_data;
2944 /* Free the global resource info table entries */
2945 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
2948 /* Free the generic table */
2949 (void)ulp_mapper_generic_tbl_list_deinit(data);
2952 /* Reset the data pointer within the ulp_ctx. */
2953 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);