1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2020 Broadcom
8 #include "ulp_template_db.h"
9 #include "ulp_template_struct.h"
10 #include "bnxt_tf_common.h"
11 #include "ulp_utils.h"
14 #include "tf_ext_flow_handle.h"
15 #include "ulp_mark_mgr.h"
16 #include "ulp_flow_db.h"
17 #include "ulp_mapper.h"
20 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms);
23 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms);
26 * Get the size of the action property for a given index.
28 * idx [in] The index for the action property
30 * returns the size of the action property.
33 ulp_mapper_act_prop_size_get(uint32_t idx)
35 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
37 return ulp_act_prop_map_table[idx];
41 * Get the list of result fields that implement the flow action
43 * ctxt [in] The ulp context
45 * tbl [in] A single table instance to get the key fields from
47 * num_flds [out] The number of key fields in the returned array
49 * returns array of Key fields, or NULL on error
51 static struct bnxt_ulp_mapper_class_key_field_info *
52 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
57 if (!tbl || !num_flds)
60 idx = tbl->key_start_idx;
61 *num_flds = tbl->key_num_fields;
63 /* NOTE: Need template to provide range checking define */
64 return &ulp_class_key_field_list[idx];
68 * Get the list of data fields that implement the flow.
70 * ctxt [in] The ulp context
72 * tbl [in] A single table instance to get the data fields from
74 * num_flds [out] The number of data fields in the returned array.
76 * Returns array of data fields, or NULL on error.
78 static struct bnxt_ulp_mapper_result_field_info *
79 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
84 if (!tbl || !num_flds)
87 idx = tbl->result_start_idx;
88 *num_flds = tbl->result_num_fields;
90 /* NOTE: Need template to provide range checking define */
91 return &ulp_class_result_field_list[idx];
95 * Get the list of result fields that implement the flow action.
97 * tbl [in] A single table instance to get the results fields
98 * from num_flds [out] The number of data fields in the returned
101 * Returns array of data fields, or NULL on error.
103 static struct bnxt_ulp_mapper_result_field_info *
104 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl,
105 uint32_t *num_rslt_flds,
106 uint32_t *num_encap_flds)
110 if (!tbl || !num_rslt_flds || !num_encap_flds)
113 idx = tbl->result_start_idx;
114 *num_rslt_flds = tbl->result_num_fields;
115 *num_encap_flds = tbl->encap_num_fields;
117 /* NOTE: Need template to provide range checking define */
118 return &ulp_act_result_field_list[idx];
122 * Get the list of ident fields that implement the flow
124 * tbl [in] A single table instance to get the ident fields from
126 * num_flds [out] The number of ident fields in the returned array
128 * returns array of ident fields, or NULL on error
130 static struct bnxt_ulp_mapper_ident_info *
131 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl,
136 if (!tbl || !num_flds)
139 idx = tbl->ident_start_idx;
140 *num_flds = tbl->ident_nums;
142 /* NOTE: Need template to provide range checking define */
143 return &ulp_ident_list[idx];
147 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
148 struct bnxt_ulp_mapper_class_tbl_info *tbl,
149 struct bnxt_ulp_mapper_ident_info *ident)
151 struct ulp_flow_db_res_params fid_parms;
154 struct tf_alloc_identifier_parms iparms = { 0 };
155 struct tf_free_identifier_parms free_parms = { 0 };
159 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
161 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
165 idx = ident->regfile_wr_idx;
167 iparms.ident_type = ident->ident_type;
168 iparms.dir = tbl->direction;
170 rc = tf_alloc_identifier(tfp, &iparms);
172 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n",
173 (iparms.dir == TF_DIR_RX) ? "RX" : "TX",
178 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
179 if (!ulp_regfile_write(parms->regfile, idx, id)) {
180 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
182 /* Need to free the identifier, so goto error */
186 /* Link the resource to the flow in the flow db */
187 memset(&fid_parms, 0, sizeof(fid_parms));
188 fid_parms.direction = tbl->direction;
189 fid_parms.resource_func = ident->resource_func;
190 fid_parms.resource_type = ident->ident_type;
191 fid_parms.resource_hndl = iparms.id;
192 fid_parms.critical_resource = 0;
194 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
199 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
201 /* Need to free the identifier, so goto error */
208 /* Need to free the identifier */
209 free_parms.dir = tbl->direction;
210 free_parms.ident_type = ident->ident_type;
211 free_parms.id = iparms.id;
213 (void)tf_free_identifier(tfp, &free_parms);
215 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
217 (tbl->direction == TF_DIR_RX) ? "RX" : "TX");
222 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms,
223 struct bnxt_ulp_mapper_result_field_info *fld,
224 struct ulp_blob *blob)
226 uint16_t idx, size_idx;
229 uint32_t val_size = 0, field_size = 0;
231 switch (fld->result_opcode) {
232 case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT:
233 val = fld->result_operand;
234 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
235 BNXT_TF_DBG(ERR, "Failed to add field\n");
239 case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP:
240 if (!ulp_operand_read(fld->result_operand,
241 (uint8_t *)&idx, sizeof(uint16_t))) {
242 BNXT_TF_DBG(ERR, "operand read failed\n");
245 idx = tfp_be_to_cpu_16(idx);
247 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
248 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
251 val = &parms->act_prop->act_details[idx];
252 field_size = ulp_mapper_act_prop_size_get(idx);
253 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) {
254 field_size = field_size -
255 ((fld->field_bit_size + 7) / 8);
258 if (!ulp_blob_push(blob, val, fld->field_bit_size)) {
259 BNXT_TF_DBG(ERR, "push field failed\n");
263 case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP_SZ:
264 if (!ulp_operand_read(fld->result_operand,
265 (uint8_t *)&idx, sizeof(uint16_t))) {
266 BNXT_TF_DBG(ERR, "operand read failed\n");
269 idx = tfp_be_to_cpu_16(idx);
271 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
272 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
275 val = &parms->act_prop->act_details[idx];
277 /* get the size index next */
278 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)],
279 (uint8_t *)&size_idx, sizeof(uint16_t))) {
280 BNXT_TF_DBG(ERR, "operand read failed\n");
283 size_idx = tfp_be_to_cpu_16(size_idx);
285 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
286 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
289 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
291 val_size = tfp_be_to_cpu_32(val_size);
292 val_size = ULP_BYTE_2_BITS(val_size);
293 ulp_blob_push_encap(blob, val, val_size);
295 case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE:
296 if (!ulp_operand_read(fld->result_operand,
297 (uint8_t *)&idx, sizeof(uint16_t))) {
298 BNXT_TF_DBG(ERR, "operand read failed\n");
302 idx = tfp_be_to_cpu_16(idx);
303 /* Uninitialized regfile entries return 0 */
304 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
305 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", idx);
309 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size);
311 BNXT_TF_DBG(ERR, "push field failed\n");
322 /* Function to alloc action record and set the table. */
324 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms,
325 struct bnxt_ulp_mapper_class_key_field_info *f,
326 struct ulp_blob *blob,
330 uint16_t idx, bitlen;
333 struct ulp_regfile *regfile = parms->regfile;
335 struct bnxt_ulp_mapper_class_key_field_info *fld = f;
339 operand = fld->spec_operand;
340 opcode = fld->spec_opcode;
342 operand = fld->mask_operand;
343 opcode = fld->mask_opcode;
346 bitlen = fld->field_bit_size;
349 case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT:
351 if (!ulp_blob_push(blob, val, bitlen)) {
352 BNXT_TF_DBG(ERR, "push to key blob failed\n");
356 case BNXT_ULP_SPEC_OPC_ADD_PAD:
357 if (!ulp_blob_pad_push(blob, bitlen)) {
358 BNXT_TF_DBG(ERR, "Pad too large for blob\n");
363 case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD:
364 if (!ulp_operand_read(operand, (uint8_t *)&idx,
366 BNXT_TF_DBG(ERR, "key operand read failed.\n");
369 idx = tfp_be_to_cpu_16(idx);
371 val = parms->hdr_field[idx].spec;
373 val = parms->hdr_field[idx].mask;
376 * Need to account for how much data was pushed to the header
377 * field vs how much is to be inserted in the key/mask.
379 field_size = parms->hdr_field[idx].size;
380 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
381 field_size = field_size - ((bitlen + 7) / 8);
385 if (!ulp_blob_push(blob, val, bitlen)) {
386 BNXT_TF_DBG(ERR, "push to key blob failed\n");
390 case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE:
391 if (!ulp_operand_read(operand, (uint8_t *)&idx,
393 BNXT_TF_DBG(ERR, "key operand read failed.\n");
396 idx = tfp_be_to_cpu_16(idx);
398 if (!ulp_regfile_read(regfile, idx, ®val)) {
399 BNXT_TF_DBG(ERR, "regfile[%d] read failed.\n",
404 val = ulp_blob_push_64(blob, ®val, bitlen);
406 BNXT_TF_DBG(ERR, "push to key blob failed\n");
416 /* Function to alloc action record and set the table. */
418 ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms,
419 struct ulp_blob *blob)
421 struct ulp_flow_db_res_params fid_parms;
422 struct tf_alloc_tbl_entry_parms alloc_parms = { 0 };
423 struct tf_free_tbl_entry_parms free_parms = { 0 };
424 struct bnxt_ulp_mapper_act_tbl_info *atbls = parms->atbls;
429 /* Set the allocation parameters for the table*/
430 alloc_parms.dir = atbls->direction;
431 alloc_parms.type = atbls->table_type;
432 alloc_parms.search_enable = atbls->srch_b4_alloc;
433 alloc_parms.result = ulp_blob_data_get(blob,
434 &alloc_parms.result_sz_in_bytes);
435 if (!alloc_parms.result) {
436 BNXT_TF_DBG(ERR, "blob is not populated\n");
440 rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms);
442 BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n",
444 (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX");
448 /* Need to calculate the idx for the result record */
450 * TBD: Need to get the stride from tflib instead of having to
451 * understand the construction of the pointer
453 uint64_t tmpidx = alloc_parms.idx;
455 if (atbls->table_type == TF_TBL_TYPE_EXT)
456 tmpidx = (alloc_parms.idx * TF_ACTION_RECORD_SZ) >> 4;
458 tmpidx = alloc_parms.idx;
460 idx = tfp_cpu_to_be_64(tmpidx);
462 /* Store the allocated index for future use in the regfile */
463 rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx);
465 BNXT_TF_DBG(ERR, "regfile[%d] write failed\n",
466 atbls->regfile_wr_idx);
472 * The set_tbl_entry API if search is not enabled or searched entry
475 if (!atbls->srch_b4_alloc || !alloc_parms.hit) {
476 struct tf_set_tbl_entry_parms set_parm = { 0 };
479 set_parm.dir = atbls->direction;
480 set_parm.type = atbls->table_type;
481 set_parm.idx = alloc_parms.idx;
482 set_parm.data = ulp_blob_data_get(blob, &length);
483 set_parm.data_sz_in_bytes = length / 8;
485 if (set_parm.type == TF_TBL_TYPE_EXT)
486 bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
487 &set_parm.tbl_scope_id);
489 set_parm.tbl_scope_id = 0;
491 /* set the table entry */
492 rc = tf_set_tbl_entry(parms->tfp, &set_parm);
494 BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n",
496 (set_parm.dir == TF_DIR_RX) ? "RX" : "TX",
502 /* Link the resource to the flow in the flow db */
503 memset(&fid_parms, 0, sizeof(fid_parms));
504 fid_parms.direction = atbls->direction;
505 fid_parms.resource_func = atbls->resource_func;
506 fid_parms.resource_type = atbls->table_type;
507 fid_parms.resource_hndl = alloc_parms.idx;
508 fid_parms.critical_resource = 0;
510 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
515 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
524 free_parms.dir = alloc_parms.dir;
525 free_parms.type = alloc_parms.type;
526 free_parms.idx = alloc_parms.idx;
528 trc = tf_free_tbl_entry(parms->tfp, &free_parms);
530 BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n");
536 * Function to process the action Info. Iterate through the list
537 * action info templates and process it.
540 ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms,
541 struct bnxt_ulp_mapper_act_tbl_info *tbl)
543 struct ulp_blob blob;
544 struct bnxt_ulp_mapper_result_field_info *flds, *fld;
545 uint32_t num_flds = 0;
546 uint32_t encap_flds = 0;
551 if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile)
554 /* use the max size if encap is enabled */
555 if (tbl->encap_num_fields)
556 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
558 bit_size = tbl->result_bit_size;
559 if (!ulp_blob_init(&blob, bit_size, parms->order)) {
560 BNXT_TF_DBG(ERR, "action blob init failed\n");
564 flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds);
565 if (!flds || !num_flds) {
566 BNXT_TF_DBG(ERR, "Template undefined for action\n");
570 for (i = 0; i < (num_flds + encap_flds); i++) {
572 rc = ulp_mapper_result_field_process(parms,
576 BNXT_TF_DBG(ERR, "Action field failed\n");
579 /* set the swap index if 64 bit swap is enabled */
580 if (parms->encap_byte_swap && encap_flds) {
581 if ((i + 1) == num_flds)
582 ulp_blob_encap_swap_idx_set(&blob);
583 /* if 64 bit swap is enabled perform the 64bit swap */
584 if ((i + 1) == (num_flds + encap_flds))
585 ulp_blob_perform_encap_swap(&blob);
589 rc = ulp_mapper_action_alloc_and_set(parms, &blob);
594 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
595 struct bnxt_ulp_mapper_class_tbl_info *tbl)
597 struct bnxt_ulp_mapper_class_key_field_info *kflds;
598 struct ulp_blob key, mask, data;
599 uint32_t i, num_kflds;
602 struct tf_alloc_tcam_entry_parms aparms = { 0 };
603 struct tf_set_tcam_entry_parms sparms = { 0 };
604 struct ulp_flow_db_res_params fid_parms = { 0 };
605 struct tf_free_tcam_entry_parms free_parms = { 0 };
609 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
611 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
615 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
616 if (!kflds || !num_kflds) {
617 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
621 if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) ||
622 !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) ||
623 !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
624 BNXT_TF_DBG(ERR, "blob inits failed.\n");
628 /* create the key/mask */
630 * NOTE: The WC table will require some kind of flag to handle the
631 * mode bits within the key/mask
633 for (i = 0; i < num_kflds; i++) {
635 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
638 BNXT_TF_DBG(ERR, "Key field set failed.\n");
643 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
646 BNXT_TF_DBG(ERR, "Mask field set failed.\n");
651 aparms.dir = tbl->direction;
652 aparms.tcam_tbl_type = tbl->table_type;
653 aparms.search_enable = tbl->srch_b4_alloc;
654 aparms.key_sz_in_bits = tbl->key_bit_size;
655 aparms.key = ulp_blob_data_get(&key, &tmplen);
656 if (tbl->key_bit_size != tmplen) {
657 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
658 tmplen, tbl->key_bit_size);
662 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
663 if (tbl->key_bit_size != tmplen) {
664 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
665 tmplen, tbl->key_bit_size);
669 aparms.priority = tbl->priority;
672 * All failures after this succeeds require the entry to be freed.
673 * cannot return directly on failure, but needs to goto error
675 rc = tf_alloc_tcam_entry(tfp, &aparms);
677 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
683 /* Build the result */
684 if (!tbl->srch_b4_alloc || !hit) {
685 struct bnxt_ulp_mapper_result_field_info *dflds;
686 struct bnxt_ulp_mapper_ident_info *idents;
687 uint32_t num_dflds, num_idents;
689 /* Alloc identifiers */
690 idents = ulp_mapper_ident_fields_get(tbl, &num_idents);
692 for (i = 0; i < num_idents; i++) {
693 rc = ulp_mapper_ident_process(parms, tbl, &idents[i]);
695 /* Already logged the error, just return */
700 /* Create the result data blob */
701 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
702 if (!dflds || !num_dflds) {
703 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
708 for (i = 0; i < num_dflds; i++) {
709 rc = ulp_mapper_result_field_process(parms,
713 BNXT_TF_DBG(ERR, "Failed to set data fields\n");
718 sparms.dir = aparms.dir;
719 sparms.tcam_tbl_type = aparms.tcam_tbl_type;
720 sparms.idx = aparms.idx;
721 /* Already verified the key/mask lengths */
722 sparms.key = ulp_blob_data_get(&key, &tmplen);
723 sparms.mask = ulp_blob_data_get(&mask, &tmplen);
724 sparms.key_sz_in_bits = tbl->key_bit_size;
725 sparms.result = ulp_blob_data_get(&data, &tmplen);
727 if (tbl->result_bit_size != tmplen) {
728 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
729 tmplen, tbl->result_bit_size);
733 sparms.result_sz_in_bits = tbl->result_bit_size;
735 rc = tf_set_tcam_entry(tfp, &sparms);
737 BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n",
738 sparms.tcam_tbl_type,
739 (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
744 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n");
749 /* Link the resource to the flow in the flow db */
750 fid_parms.direction = tbl->direction;
751 fid_parms.resource_func = tbl->resource_func;
752 fid_parms.resource_type = tbl->table_type;
753 fid_parms.critical_resource = tbl->critical_resource;
754 fid_parms.resource_hndl = aparms.idx;
756 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
761 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
763 /* Need to free the identifier, so goto error */
769 free_parms.dir = tbl->direction;
770 free_parms.tcam_tbl_type = tbl->table_type;
771 free_parms.idx = aparms.idx;
772 trc = tf_free_tcam_entry(tfp, &free_parms);
774 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
775 tbl->table_type, tbl->direction, aparms.idx);
781 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
782 struct bnxt_ulp_mapper_class_tbl_info *tbl)
784 struct bnxt_ulp_mapper_class_key_field_info *kflds;
785 struct bnxt_ulp_mapper_result_field_info *dflds;
786 struct ulp_blob key, data;
787 uint32_t i, num_kflds, num_dflds;
789 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
790 struct ulp_rte_act_prop *a_prop = parms->act_prop;
791 struct ulp_flow_db_res_params fid_parms = { 0 };
792 struct tf_insert_em_entry_parms iparms = { 0 };
793 struct tf_delete_em_entry_parms free_parms = { 0 };
797 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds);
798 if (!kflds || !num_kflds) {
799 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
803 /* Initialize the key/result blobs */
804 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) ||
805 !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
806 BNXT_TF_DBG(ERR, "blob inits failed.\n");
811 for (i = 0; i < num_kflds; i++) {
813 rc = ulp_mapper_keymask_field_process(parms, &kflds[i],
816 BNXT_TF_DBG(ERR, "Key field set failed.\n");
822 * TBD: Normally should process identifiers in case of using recycle or
823 * loopback. Not supporting recycle for now.
826 /* Create the result data blob */
827 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds);
828 if (!dflds || !num_dflds) {
829 BNXT_TF_DBG(ERR, "Failed to get data fields.\n");
833 for (i = 0; i < num_dflds; i++) {
834 struct bnxt_ulp_mapper_result_field_info *fld;
838 rc = ulp_mapper_result_field_process(parms,
842 BNXT_TF_DBG(ERR, "Failed to set data fields.\n");
847 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
848 &iparms.tbl_scope_id);
850 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
855 * NOTE: the actual blob size will differ from the size in the tbl
856 * entry due to the padding.
858 iparms.dup_check = 0;
859 iparms.dir = tbl->direction;
860 iparms.mem = tbl->mem;
861 iparms.key = ulp_blob_data_get(&key, &tmplen);
862 iparms.key_sz_in_bits = tbl->key_bit_size;
863 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
864 iparms.em_record_sz_in_bits = tbl->result_bit_size;
866 rc = tf_insert_em_entry(tfp, &iparms);
868 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
872 if (tbl->mark_enable &&
873 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
874 BNXT_ULP_ACTION_BIT_MARK)) {
875 uint32_t val, mark, gfid, flag;
876 /* TBD: Need to determine if GFID is enabled globally */
877 if (sizeof(val) != BNXT_ULP_ACT_PROP_SZ_MARK) {
878 BNXT_TF_DBG(ERR, "Mark size (%d) != expected (%zu)\n",
879 BNXT_ULP_ACT_PROP_SZ_MARK, sizeof(val));
885 &a_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
888 mark = tfp_be_to_cpu_32(val);
890 TF_GET_GFID_FROM_FLOW_ID(iparms.flow_id, gfid);
891 TF_GET_FLAG_FROM_FLOW_ID(iparms.flow_id, flag);
893 rc = ulp_mark_db_mark_add(parms->ulp_ctx,
894 (flag == TF_GFID_TABLE_EXTERNAL),
898 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
903 * Link the mark resource to the flow in the flow db
904 * The mark is never the critical resource, so it is 0.
906 memset(&fid_parms, 0, sizeof(fid_parms));
907 fid_parms.direction = tbl->direction;
908 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
909 fid_parms.resource_type = tbl->table_type;
910 fid_parms.resource_hndl = iparms.flow_id;
911 fid_parms.critical_resource = 0;
913 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
918 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
920 /* Need to free the identifier, so goto error */
925 /* Link the EM resource to the flow in the flow db */
926 memset(&fid_parms, 0, sizeof(fid_parms));
927 fid_parms.direction = tbl->direction;
928 fid_parms.resource_func = tbl->resource_func;
929 fid_parms.resource_type = tbl->table_type;
930 fid_parms.critical_resource = tbl->critical_resource;
931 fid_parms.resource_hndl = iparms.flow_handle;
933 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
938 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
940 /* Need to free the identifier, so goto error */
946 free_parms.dir = iparms.dir;
947 free_parms.mem = iparms.mem;
948 free_parms.tbl_scope_id = iparms.tbl_scope_id;
949 free_parms.flow_handle = iparms.flow_handle;
951 trc = tf_delete_em_entry(tfp, &free_parms);
953 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
959 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
960 struct bnxt_ulp_mapper_class_tbl_info *tbl)
962 struct bnxt_ulp_mapper_result_field_info *flds;
963 struct ulp_flow_db_res_params fid_parms;
964 struct ulp_blob data;
967 uint32_t i, num_flds;
968 int32_t rc = 0, trc = 0;
969 struct tf_alloc_tbl_entry_parms aparms = { 0 };
970 struct tf_set_tbl_entry_parms sparms = { 0 };
971 struct tf_free_tbl_entry_parms free_parms = { 0 };
973 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
975 if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) {
976 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
980 flds = ulp_mapper_result_fields_get(tbl, &num_flds);
981 if (!flds || !num_flds) {
982 BNXT_TF_DBG(ERR, "Template undefined for action\n");
986 for (i = 0; i < num_flds; i++) {
987 rc = ulp_mapper_result_field_process(parms,
991 BNXT_TF_DBG(ERR, "data field failed\n");
996 aparms.dir = tbl->direction;
997 aparms.type = tbl->table_type;
998 aparms.search_enable = tbl->srch_b4_alloc;
999 aparms.result = ulp_blob_data_get(&data, &tmplen);
1000 aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1002 /* All failures after the alloc succeeds require a free */
1003 rc = tf_alloc_tbl_entry(tfp, &aparms);
1005 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n",
1007 (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1012 /* Always storing values in Regfile in BE */
1013 idx = tfp_cpu_to_be_64(aparms.idx);
1014 rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx);
1016 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
1017 tbl->regfile_wr_idx);
1021 if (!tbl->srch_b4_alloc) {
1022 sparms.dir = tbl->direction;
1023 sparms.type = tbl->table_type;
1024 sparms.data = ulp_blob_data_get(&data, &tmplen);
1025 sparms.data_sz_in_bytes =
1026 ULP_SZ_BITS2BYTES(tbl->result_bit_size);
1027 sparms.idx = aparms.idx;
1029 rc = tf_set_tbl_entry(tfp, &sparms);
1031 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n",
1033 (tbl->direction == TF_DIR_RX) ? "RX" : "TX",
1041 /* Link the resource to the flow in the flow db */
1042 memset(&fid_parms, 0, sizeof(fid_parms));
1043 fid_parms.direction = tbl->direction;
1044 fid_parms.resource_func = tbl->resource_func;
1045 fid_parms.resource_type = tbl->table_type;
1046 fid_parms.resource_hndl = aparms.idx;
1047 fid_parms.critical_resource = 0;
1049 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1054 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1062 * Free the allocated resource since we failed to either
1063 * write to the entry or link the flow
1065 free_parms.dir = tbl->direction;
1066 free_parms.type = tbl->table_type;
1067 free_parms.idx = aparms.idx;
1069 trc = tf_free_tbl_entry(tfp, &free_parms);
1071 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
1077 * Function to process the action template. Iterate through the list
1078 * action info templates and process it.
1081 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1086 if (!parms->atbls || !parms->num_atbls) {
1087 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n",
1088 parms->dev_id, parms->act_tid);
1092 for (i = 0; i < parms->num_atbls; i++) {
1093 rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]);
1101 /* Create the classifier table entries for a flow. */
1103 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms)
1111 if (!parms->ctbls || !parms->num_ctbls) {
1112 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n",
1113 parms->dev_id, parms->class_tid);
1117 for (i = 0; i < parms->num_ctbls; i++) {
1118 struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i];
1120 switch (tbl->resource_func) {
1121 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
1122 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
1124 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
1125 rc = ulp_mapper_em_tbl_process(parms, tbl);
1127 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
1128 rc = ulp_mapper_index_tbl_process(parms, tbl);
1131 BNXT_TF_DBG(ERR, "Unexpected class resource %d\n",
1132 tbl->resource_func);
1137 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
1138 tbl->resource_func);