+ return 0;
+
+error:
+ /* Need to free the identifier */
+ free_parms.dir = tbl->direction;
+ free_parms.ident_type = ident->ident_type;
+ free_parms.id = sparms.search_id;
+ (void)tf_free_identifier(tfp, &free_parms);
+ BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
+ ident->description,
+ tf_dir_2_str(tbl->direction), sparms.search_id);
+ return rc;
+}
+
+static int32_t
+ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
+ uint32_t port_id,
+ uint16_t val16,
+ uint8_t **val)
+{
+ enum bnxt_ulp_port_table port_data = val16;
+
+ switch (port_data) {
+ case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
+ if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
+ val)) {
+ BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
+ return -EINVAL;
+ }
+ break;
+ case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
+ if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
+ val)) {
+ BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
+ return -EINVAL;
+ }
+ break;
+ case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
+ if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
+ val)) {
+ BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int32_t
+ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
+ enum bnxt_ulp_field_src field_src,
+ uint8_t *field_opr,
+ enum tf_dir dir,
+ uint8_t is_key,
+ uint32_t bitlen,
+ uint8_t **val,
+ uint32_t *val_len,
+ uint64_t *value)
+{
+ struct bnxt_ulp_mapper_data *m;
+ uint8_t bit;
+ uint32_t port_id, val_size, field_size;
+ uint16_t idx, size_idx, offset;
+ uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
+ uint8_t *buffer;
+ uint64_t lregval;
+ bool shared;
+
+ *val_len = bitlen;
+ *value = 0;
+ /* Perform the action */
+ switch (field_src) {
+ case BNXT_ULP_FIELD_SRC_ZERO:
+ *val = mapper_fld_zeros;
+ break;
+ case BNXT_ULP_FIELD_SRC_CONST:
+ *val = field_opr;
+ break;
+ case BNXT_ULP_FIELD_SRC_ONES:
+ *val = mapper_fld_ones;
+ *value = 1;
+ break;
+ case BNXT_ULP_FIELD_SRC_CF:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "CF operand read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
+ BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
+ bytelen);
+ return -EINVAL;
+ }
+ buffer = (uint8_t *)&parms->comp_fld[idx];
+ *val = &buffer[sizeof(uint64_t) - bytelen];
+ *value = ULP_COMP_FLD_IDX_RD(parms, idx);
+ break;
+ case BNXT_ULP_FIELD_SRC_RF:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "RF operand read failed\n");
+ return -EINVAL;
+ }
+
+ idx = tfp_be_to_cpu_16(idx);
+ /* Uninitialized regfile entries return 0 */
+ if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
+ sizeof(uint64_t) < bytelen) {
+ BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
+ bytelen);
+ return -EINVAL;
+ }
+ buffer = (uint8_t *)&parms->regfile->entry[idx].data;
+ *val = &buffer[sizeof(uint64_t) - bytelen];
+ *value = tfp_be_to_cpu_64(lregval);
+ break;
+ case BNXT_ULP_FIELD_SRC_ACT_PROP:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Action operand read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
+ return -EINVAL;
+ }
+ buffer = &parms->act_prop->act_details[idx];
+ field_size = ulp_mapper_act_prop_size_get(idx);
+ if (bytelen > field_size) {
+ BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
+ idx, field_size);
+ return -EINVAL;
+ }
+ *val = &buffer[field_size - bytelen];
+ break;
+ case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+
+ if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
+ return -EINVAL;
+ }
+ *val = &parms->act_prop->act_details[idx];
+
+ /* get the size index next */
+ if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
+ (uint8_t *)&size_idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
+ return -EINVAL;
+ }
+ size_idx = tfp_be_to_cpu_16(size_idx);
+ if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
+ BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
+ return -EINVAL;
+ }
+ memcpy(&val_size, &parms->act_prop->act_details[size_idx],
+ sizeof(uint32_t));
+ val_size = tfp_be_to_cpu_32(val_size);
+ *val_len = ULP_BYTE_2_BITS(val_size);
+ break;
+ case BNXT_ULP_FIELD_SRC_GLB_RF:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Global regfile read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (ulp_mapper_glb_resource_read(parms->mapper_data,
+ dir, idx, &lregval, &shared) ||
+ sizeof(uint64_t) < bytelen) {
+ BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
+ idx, bytelen);
+ return -EINVAL;
+ }
+ m = parms->mapper_data;
+ buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
+ *val = &buffer[sizeof(uint64_t) - bytelen];
+ *value = tfp_be_to_cpu_64(lregval);
+ break;
+ case BNXT_ULP_FIELD_SRC_HF:
+ case BNXT_ULP_FIELD_SRC_SUB_HF:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Header field read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ /* get the index from the global field list */
+ if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
+ BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
+ idx);
+ return -EINVAL;
+ }
+ if (is_key)
+ buffer = parms->hdr_field[bit].spec;
+ else
+ buffer = parms->hdr_field[bit].mask;
+
+ field_size = parms->hdr_field[bit].size;
+ if (bytelen > field_size) {
+ BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
+ bit, field_size);
+ return -EINVAL;
+ }
+ if (field_src == BNXT_ULP_FIELD_SRC_HF) {
+ *val = &buffer[field_size - bytelen];
+ } else {
+ /* get the offset next */
+ if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
+ (uint8_t *)&offset,
+ sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
+ return -EINVAL;
+ }
+ offset = tfp_be_to_cpu_16(offset);
+ offset = ULP_BITS_2_BYTE_NR(offset);
+ if ((offset + bytelen) > field_size) {
+ BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
+ return -EINVAL;
+ }
+ *val = &buffer[offset];
+ }
+ break;
+ case BNXT_ULP_FIELD_SRC_HDR_BIT:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&lregval, sizeof(uint64_t))) {
+ BNXT_TF_DBG(ERR, "Header bit read failed\n");
+ return -EINVAL;
+ }
+ lregval = tfp_be_to_cpu_64(lregval);
+ if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
+ *val = mapper_fld_one;
+ *value = 1;
+ } else {
+ *val = mapper_fld_zeros;
+ }
+ break;
+ case BNXT_ULP_FIELD_SRC_ACT_BIT:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&lregval, sizeof(uint64_t))) {
+ BNXT_TF_DBG(ERR, "Action bit read failed\n");
+ return -EINVAL;
+ }
+ lregval = tfp_be_to_cpu_64(lregval);
+ if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
+ *val = mapper_fld_one;
+ *value = 1;
+ } else {
+ *val = mapper_fld_zeros;
+ }
+ break;
+ case BNXT_ULP_FIELD_SRC_FIELD_BIT:
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Field bit read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ /* get the index from the global field list */
+ if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
+ BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
+ idx);
+ return -EINVAL;
+ }
+ if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
+ *val = mapper_fld_one;
+ *value = 1;
+ } else {
+ *val = mapper_fld_zeros;
+ }
+ break;
+ case BNXT_ULP_FIELD_SRC_PORT_TABLE:
+ /* The port id is present in the comp field list */
+ port_id = ULP_COMP_FLD_IDX_RD(parms,
+ BNXT_ULP_CF_IDX_DEV_PORT_ID);
+ /* get the port table enum */
+ if (!ulp_operand_read(field_opr,
+ (uint8_t *)&idx, sizeof(uint16_t))) {
+ BNXT_TF_DBG(ERR, "Port table enum read failed\n");
+ return -EINVAL;
+ }
+ idx = tfp_be_to_cpu_16(idx);
+ if (ulp_mapper_field_port_db_process(parms, port_id, idx,
+ val)) {
+ BNXT_TF_DBG(ERR, "field port table failed\n");
+ return -EINVAL;
+ }
+ case BNXT_ULP_FIELD_SRC_SKIP:
+ /* do nothing */
+ break;
+ case BNXT_ULP_FIELD_SRC_REJECT:
+ return -EINVAL;
+ default:
+ BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
+ uint64_t *output)
+{
+ uint16_t val_16;
+ uint32_t val_32;
+ uint64_t val_64;
+ uint32_t bytelen;
+
+ bytelen = ULP_BITS_2_BYTE(bitlen);
+ if (bytelen == sizeof(uint8_t)) {
+ *output = *((uint8_t *)buffer);
+ } else if (bytelen == sizeof(uint16_t)) {
+ val_16 = *((uint16_t *)buffer);
+ *output = tfp_be_to_cpu_16(val_16);
+ } else if (bytelen == sizeof(uint32_t)) {
+ val_32 = *((uint32_t *)buffer);
+ *output = tfp_be_to_cpu_32(val_32);
+ } else if (bytelen == sizeof(val_64)) {
+ val_64 = *((uint64_t *)buffer);
+ *output = tfp_be_to_cpu_64(val_64);
+ } else {
+ *output = 0;
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
+ struct ulp_blob *blob,
+ uint8_t *val,
+ uint32_t val_len,
+ uint8_t **out_val)
+{
+ if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
+ if (ulp_blob_pad_push(blob, val_len) < 0) {
+ BNXT_TF_DBG(ERR, "too large for blob\n");
+ return -EINVAL;
+ }
+ } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
+ if (ulp_blob_push_encap(blob, val, val_len) < 0) {
+ BNXT_TF_DBG(ERR, "encap blob push failed\n");
+ return -EINVAL;
+ }
+ } else {
+ if (!ulp_blob_push(blob, val, val_len)) {
+ BNXT_TF_DBG(ERR, "push of val1 failed\n");
+ return -EINVAL;
+ }
+ }
+ *out_val = val;
+ return 0;
+}
+
+static int32_t
+ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
+ enum tf_dir dir,
+ struct bnxt_ulp_mapper_field_info *fld,
+ struct ulp_blob *blob,
+ uint8_t is_key,
+ const char *name)
+{
+ uint16_t write_idx = blob->write_idx;
+ uint8_t *val = NULL, *val1, *val2, *val3;
+ uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
+ uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
+ uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
+ uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
+ uint64_t value1 = 0, value2 = 0, value3 = 0;
+ int32_t rc = 0;
+
+ /* prepare the field source and values */
+ switch (fld->field_opc) {
+ case BNXT_ULP_FIELD_OPC_SRC1:
+ process_src1 = 1;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
+ process_src1 = 1;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
+ case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
+ process_src3 = 1;
+ eval_src3 = 1;
+ process_src1 = 1;
+ process_src2 = 1;
+ eval_src1 = 1;
+ eval_src2 = 1;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
+ case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
+ case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
+ case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
+ case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
+ case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
+ process_src1 = 1;
+ process_src2 = 1;
+ eval_src1 = 1;
+ eval_src2 = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* process the src1 opcode */
+ if (process_src1) {
+ if (ulp_mapper_field_src_process(parms, fld->field_src1,
+ fld->field_opr1, dir, is_key,
+ fld->field_bit_size, &val1,
+ &val1_len, &value1)) {
+ BNXT_TF_DBG(ERR, "fld src1 process failed\n");
+ goto error;
+ }
+ if (eval_src1) {
+ if (ulp_mapper_field_buffer_eval(val1, val1_len,
+ &val1_int)) {
+ BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
+ goto error;
+ }
+ }
+ }
+
+ /* for "if then clause" set the correct process */
+ if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
+ if (value1)
+ process_src2 = 1;
+ else
+ process_src3 = 1;
+ }
+
+ /* process src2 opcode */
+ if (process_src2) {
+ if (ulp_mapper_field_src_process(parms, fld->field_src2,
+ fld->field_opr2, dir, is_key,
+ fld->field_bit_size, &val2,
+ &val2_len, &value2)) {
+ BNXT_TF_DBG(ERR, "fld src2 process failed\n");
+ goto error;
+ }
+ if (eval_src2) {
+ if (ulp_mapper_field_buffer_eval(val2, val2_len,
+ &val2_int)) {
+ BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
+ goto error;
+ }
+ }
+ }
+
+ /* process src3 opcode */
+ if (process_src3) {
+ if (ulp_mapper_field_src_process(parms, fld->field_src3,
+ fld->field_opr3, dir, is_key,
+ fld->field_bit_size, &val3,
+ &val3_len, &value3)) {
+ BNXT_TF_DBG(ERR, "fld src3 process failed\n");
+ goto error;
+ }
+ if (eval_src3) {
+ if (ulp_mapper_field_buffer_eval(val3, val3_len,
+ &val3_int)) {
+ BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
+ goto error;
+ }
+ }
+ }
+
+ val_len = fld->field_bit_size;
+ /* process the field opcodes */
+ switch (fld->field_opc) {
+ case BNXT_ULP_FIELD_OPC_SRC1:
+ rc = ulp_mapper_field_blob_write(fld->field_src1,
+ blob, val1, val1_len, &val);
+ val_len = val1_len;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
+ if (value1) {
+ rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
+ val2, val2_len, &val);
+ val_len = val2_len;
+ } else {
+ rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
+ val3, val3_len, &val);
+ val_len = val3_len;
+ }
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
+ case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
+ val_int = val1_int + val2_int;
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
+ case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
+ val_int = val1_int - val2_int;
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
+ val_int = val1_int | val2_int;
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
+ val_int = val1_int | val2_int | val3_int;
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
+ val_int = val1_int & val2_int;
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
+ val_int = val1_int & (val2_int | val3_int);
+ val_int = tfp_cpu_to_be_64(val_int);
+ val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
+ if (!val)
+ rc = -EINVAL;
+ break;
+ case BNXT_ULP_FIELD_OPC_SKIP:
+ break;
+ default:
+ BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+error:
+ BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
+ fld->description, (val) ? write_idx : 0, val_len);
+ return -EINVAL;
+}
+
+/*
+ * Result table process and fill the result blob.
+ * data [out] - the result blob data
+ */
+static int32_t
+ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ struct ulp_blob *data,
+ const char *name)
+{
+ struct bnxt_ulp_mapper_field_info *dflds;
+ uint32_t i, num_flds = 0, encap_flds = 0;
+ int32_t rc = 0;
+
+ /* Get the result field list */
+ dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
+ &encap_flds);
+
+ /* validate the result field list counts */
+ if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
+ (!num_flds && !encap_flds)) || !dflds ||
+ (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
+ (!num_flds || encap_flds))) {
+ BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
+ num_flds, encap_flds);
+ return -EINVAL;
+ }
+
+ /* process the result fields, loop through them */
+ for (i = 0; i < (num_flds + encap_flds); i++) {
+ /* set the swap index if encap swap bit is enabled */
+ if (parms->device_params->encap_byte_swap && encap_flds &&
+ i == num_flds)
+ ulp_blob_encap_swap_idx_set(data);
+
+ /* Process the result fields */
+ rc = ulp_mapper_field_opc_process(parms, tbl->direction,
+ &dflds[i], data, 0, name);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "data field failed\n");
+ return rc;
+ }
+ }
+
+ /* if encap bit swap is enabled perform the bit swap */
+ if (parms->device_params->encap_byte_swap && encap_flds)
+ ulp_blob_perform_encap_swap(data);
+
+ return rc;
+}
+
+static int32_t
+ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ uint64_t flow_id)
+{
+ struct ulp_flow_db_res_params fid_parms;
+ uint32_t mark, gfid, mark_flag;
+ enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
+ int32_t rc = 0;
+
+ if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
+ !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
+ ULP_BITMAP_ISSET(parms->act_bitmap->bits,
+ BNXT_ULP_ACT_BIT_MARK)))
+ return rc; /* no need to perform gfid process */
+
+ /* Get the mark id details from action property */
+ memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
+ sizeof(mark));
+ mark = tfp_be_to_cpu_32(mark);
+
+ TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
+ mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
+
+ rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
+ gfid, mark);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
+ return rc;
+ }
+ fid_parms.direction = tbl->direction;
+ fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
+ fid_parms.critical_resource = tbl->critical_resource;
+ fid_parms.resource_type = mark_flag;
+ fid_parms.resource_hndl = gfid;
+ ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
+
+ rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
+ return rc;
+}
+
+static int32_t
+ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct ulp_flow_db_res_params fid_parms;
+ uint32_t act_idx, mark, mark_flag;
+ uint64_t val64;
+ enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
+ int32_t rc = 0;
+
+ if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
+ !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
+ ULP_BITMAP_ISSET(parms->act_bitmap->bits,
+ BNXT_ULP_ACT_BIT_MARK)))
+ return rc; /* no need to perform mark action process */
+
+ /* Get the mark id details from action property */
+ memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
+ sizeof(mark));
+ mark = tfp_be_to_cpu_32(mark);
+
+ if (!ulp_regfile_read(parms->regfile,
+ BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
+ &val64)) {
+ BNXT_TF_DBG(ERR, "read action ptr main failed\n");
+ return -EINVAL;
+ }
+ act_idx = tfp_be_to_cpu_64(val64);
+ mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
+ rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
+ act_idx, mark);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
+ return rc;
+ }
+ fid_parms.direction = tbl->direction;
+ fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
+ fid_parms.critical_resource = tbl->critical_resource;
+ fid_parms.resource_type = mark_flag;
+ fid_parms.resource_hndl = act_idx;
+ ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
+
+ rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
+ return rc;
+}
+
+static int32_t
+ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct ulp_flow_db_res_params fid_parms;
+ uint32_t act_idx, mark, mark_flag;
+ uint64_t val64;
+ enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
+ int32_t rc = 0;
+
+ if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
+ mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
+ return rc; /* no need to perform mark action process */
+
+ /* Get the mark id details from the computed field of dev port id */
+ mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
+
+ /* Get the main action pointer */
+ if (!ulp_regfile_read(parms->regfile,
+ BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
+ &val64)) {
+ BNXT_TF_DBG(ERR, "read action ptr main failed\n");
+ return -EINVAL;
+ }
+ act_idx = tfp_be_to_cpu_64(val64);
+
+ /* Set the mark flag to local fid and vfr flag */
+ mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
+
+ rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
+ act_idx, mark);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
+ return rc;
+ }
+ fid_parms.direction = tbl->direction;
+ fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
+ fid_parms.critical_resource = tbl->critical_resource;
+ fid_parms.resource_type = mark_flag;
+ fid_parms.resource_hndl = act_idx;
+ ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
+
+ rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
+ if (rc)
+ BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
+ return rc;
+}
+
+/* Tcam table scan the identifier list and allocate each identifier */
+static int32_t
+ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct bnxt_ulp_mapper_ident_info *idents;
+ uint32_t num_idents;
+ uint32_t i;
+
+ idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
+ for (i = 0; i < num_idents; i++) {
+ if (ulp_mapper_ident_process(parms, tbl,
+ &idents[i], NULL))
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Tcam table scan the identifier list and extract the identifier from
+ * the result blob.
+ */
+static int32_t
+ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ struct ulp_blob *data)
+{
+ struct bnxt_ulp_mapper_ident_info *idents;
+ uint32_t num_idents = 0, i;
+ int32_t rc = 0;
+
+ /*
+ * Extract the listed identifiers from the result field,
+ * no need to allocate them.
+ */
+ idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
+ for (i = 0; i < num_idents; i++) {
+ rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
+ return rc;
+ }
+ }
+ return rc;
+}
+
+/* Internal function to write the tcam entry */
+static int32_t
+ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ struct ulp_blob *key,
+ struct ulp_blob *mask,
+ struct ulp_blob *data,
+ uint16_t idx)
+{
+ struct tf_set_tcam_entry_parms sparms = { 0 };
+ struct tf *tfp;
+ uint16_t tmplen;
+ int32_t rc;
+
+ tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
+ if (!tfp) {
+ BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
+ return -EINVAL;
+ }
+
+ sparms.dir = tbl->direction;
+ sparms.tcam_tbl_type = tbl->resource_type;
+ sparms.idx = idx;
+ sparms.key = ulp_blob_data_get(key, &tmplen);
+ sparms.key_sz_in_bits = tmplen;
+ sparms.mask = ulp_blob_data_get(mask, &tmplen);
+ sparms.result = ulp_blob_data_get(data, &tmplen);
+ sparms.result_sz_in_bits = tmplen;
+ if (tf_set_tcam_entry(tfp, &sparms)) {
+ BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
+ tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
+ tf_dir_2_str(sparms.dir), sparms.idx);
+ return -EIO;
+ }
+
+ /* Mark action */
+ rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "failed mark action processing\n");
+ return rc;
+ }
+
+ return rc;
+}
+
+/*
+ * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
+ *
+ * parms [in] The mappers parms with data related to the flow.
+ *
+ * key [in] The original key to be transformed
+ *
+ * mask [in] The original mask to be transformed
+ *
+ * tkey [in/out] The transformed key
+ *
+ * tmask [in/out] The transformed mask
+ *
+ * returns zero on success, non-zero on failure
+ */
+static uint32_t
+ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
+ struct ulp_blob *key,
+ struct ulp_blob *mask,
+ struct ulp_blob *tkey,
+ struct ulp_blob *tmask)
+{
+ uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
+ uint32_t cword, i, rc;
+ int32_t pad;
+ uint8_t *val;
+
+ slice_width = dparms->wc_slice_width;
+ clen = dparms->wc_ctl_size_bits;
+ max_slices = dparms->wc_max_slices;
+ blen = ulp_blob_data_len_get(key);
+
+ /* Get the length of the key based on number of slices and width */
+ num_slices = 1;
+ tlen = slice_width;
+ while (tlen < blen &&
+ num_slices <= max_slices) {
+ num_slices = num_slices << 1;
+ tlen = tlen << 1;
+ }
+
+ if (num_slices > max_slices) {
+ BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
+ return -EINVAL;
+ }
+
+ /* The key/mask may not be on a natural slice boundary, pad it */
+ pad = tlen - blen;
+ if (ulp_blob_pad_push(key, pad) < 0 ||
+ ulp_blob_pad_push(mask, pad) < 0) {
+ BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
+ return -EINVAL;
+ }
+
+ /* The new length accounts for the ctrl word length and num slices */
+ tlen = tlen + clen * num_slices;
+ if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
+ !ulp_blob_init(tmask, tlen, mask->byte_order)) {
+ BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
+ return -EINVAL;
+ }
+
+ /* Build the transformed key/mask */
+ cword = dparms->wc_mode_list[num_slices - 1];
+ cword = tfp_cpu_to_be_32(cword);
+ offset = 0;
+ for (i = 0; i < num_slices; i++) {
+ val = ulp_blob_push_32(tkey, &cword, clen);
+ if (!val) {
+ BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
+ return -EINVAL;
+ }
+ val = ulp_blob_push_32(tmask, &cword, clen);
+ if (!val) {
+ BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
+ return -EINVAL;
+ }
+ rc = ulp_blob_append(tkey, key, offset, slice_width);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Key blob append failed\n");
+ return rc;
+ }
+ rc = ulp_blob_append(tmask, mask, offset, slice_width);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Mask blob append failed\n");
+ return rc;
+ }
+ offset += slice_width;
+ }
+
+ /* The key/mask are byte reversed on every 4 byte chunk */
+ ulp_blob_perform_byte_reverse(tkey, 4);
+ ulp_blob_perform_byte_reverse(tmask, 4);
+
+ return 0;
+}
+
+/* internal function to post process the key/mask blobs for wildcard tcam tbl */
+static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
+{
+ ulp_blob_perform_64B_word_swap(blob);
+ ulp_blob_perform_64B_byte_swap(blob);
+}
+
+static int32_t
+ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct bnxt_ulp_mapper_key_info *kflds;
+ struct ulp_blob okey, omask, data, update_data;
+ struct ulp_blob tkey, tmask; /* transform key and mask */
+ struct ulp_blob *key, *mask;
+ uint32_t i, num_kflds;
+ struct tf *tfp;
+ int32_t rc, trc;
+ struct bnxt_ulp_device_params *dparms = parms->device_params;
+ struct tf_alloc_tcam_entry_parms aparms = { 0 };
+ struct tf_search_tcam_entry_parms searchparms = { 0 };
+ struct ulp_flow_db_res_params fid_parms = { 0 };
+ struct tf_free_tcam_entry_parms free_parms = { 0 };
+ uint32_t hit = 0;
+ uint16_t tmplen = 0;
+ uint16_t idx;
+
+ /* Set the key and mask to the original key and mask. */
+ key = &okey;
+ mask = &omask;
+
+ /* Skip this if table opcode is NOP */
+ if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
+ tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
+ BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
+ tbl->tbl_opcode);
+ return 0;
+ }
+
+ tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
+ if (!tfp) {
+ BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
+ return -EINVAL;
+ }
+
+ kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
+ if (!kflds || !num_kflds) {
+ BNXT_TF_DBG(ERR, "Failed to get key fields\n");
+ return -EINVAL;
+ }
+
+ if (!ulp_blob_init(key, tbl->blob_key_bit_size, tbl->byte_order) ||
+ !ulp_blob_init(mask, tbl->blob_key_bit_size, tbl->byte_order) ||
+ !ulp_blob_init(&data, tbl->result_bit_size, dparms->byte_order) ||
+ !ulp_blob_init(&update_data, tbl->result_bit_size,
+ dparms->byte_order)) {
+ BNXT_TF_DBG(ERR, "blob inits failed.\n");
+ return -EINVAL;
+ }
+
+ /* create the key/mask */
+ /*
+ * NOTE: The WC table will require some kind of flag to handle the
+ * mode bits within the key/mask
+ */
+ for (i = 0; i < num_kflds; i++) {
+ /* Setup the key */
+ rc = ulp_mapper_field_opc_process(parms, tbl->direction,
+ &kflds[i].field_info_spec,
+ key, 1, "TCAM Key");
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Key field set failed %s\n",
+ kflds[i].field_info_spec.description);
+ return rc;
+ }
+
+ /* Setup the mask */
+ rc = ulp_mapper_field_opc_process(parms, tbl->direction,
+ &kflds[i].field_info_mask,
+ mask, 0, "TCAM Mask");
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
+ kflds[i].field_info_mask.description);
+ return rc;
+ }
+ }
+
+ /* For wild card tcam perform the post process to swap the blob */
+ if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
+ tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
+ tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) {
+ if (dparms->dynamic_pad_en) {
+ /* Sets up the slices for writing to the WC TCAM */
+ rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
+ key, mask,
+ &tkey,
+ &tmask);
+ if (rc) {
+ BNXT_TF_DBG(ERR,
+ "Failed to post proc WC entry.\n");
+ return rc;
+ }
+ /* Now need to use the transform Key/Mask */
+ key = &tkey;
+ mask = &tmask;
+ } else {
+ ulp_mapper_wc_tcam_tbl_post_process(key);
+ ulp_mapper_wc_tcam_tbl_post_process(mask);
+ }
+
+ }
+
+ if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
+ /* allocate the tcam index */
+ aparms.dir = tbl->direction;
+ aparms.tcam_tbl_type = tbl->resource_type;
+ aparms.key = ulp_blob_data_get(key, &tmplen);
+ aparms.key_sz_in_bits = tmplen;
+ aparms.mask = ulp_blob_data_get(mask, &tmplen);
+
+ /* calculate the entry priority */
+ rc = ulp_mapper_priority_opc_process(parms, tbl,
+ &aparms.priority);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "entry priority process failed\n");
+ return rc;
+ }
+
+ rc = tf_alloc_tcam_entry(tfp, &aparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
+ return rc;
+ }
+ idx = aparms.idx;
+ hit = aparms.hit;
+ } else {
+ /*
+ * Searching before allocation to see if we already have an
+ * entry. This allows re-use of a constrained resource.
+ */
+ searchparms.dir = tbl->direction;
+ searchparms.tcam_tbl_type = tbl->resource_type;
+ searchparms.key = ulp_blob_data_get(key, &tmplen);
+ searchparms.key_sz_in_bits = tbl->key_bit_size;
+ searchparms.mask = ulp_blob_data_get(mask, &tmplen);
+ searchparms.alloc = 1;
+ searchparms.result = ulp_blob_data_get(&data, &tmplen);
+ searchparms.result_sz_in_bits = tbl->result_bit_size;
+
+ /* calculate the entry priority */
+ rc = ulp_mapper_priority_opc_process(parms, tbl,
+ &searchparms.priority);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "entry priority process failed\n");
+ return rc;
+ }
+
+ rc = tf_search_tcam_entry(tfp, &searchparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Successful search, check the result */
+ if (searchparms.search_status == REJECT) {
+ BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
+ return -ENOMEM;
+ }
+ idx = searchparms.idx;
+ hit = searchparms.hit;
+ }
+
+ /* Write the tcam index into the regfile*/
+ if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
+ (uint64_t)tfp_cpu_to_be_64(idx))) {
+ BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
+ tbl->tbl_operand);
+ rc = -EINVAL;
+ /* Need to free the tcam idx, so goto error */
+ goto error;
+ }
+
+ /* if it is miss then it is same as no search before alloc */
+ if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
+ /*Scan identifier list, allocate identifier and update regfile*/
+ rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
+ /* Create the result blob */
+ if (!rc)
+ rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
+ "TCAM Result");
+ /* write the tcam entry */
+ if (!rc)
+ rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
+ mask, &data, idx);
+ } else {
+ /*Scan identifier list, extract identifier and update regfile*/
+ rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
+ }
+ if (rc)
+ goto error;
+
+ /* Add the tcam index to the flow database */
+ fid_parms.direction = tbl->direction;
+ fid_parms.resource_func = tbl->resource_func;
+ fid_parms.resource_type = tbl->resource_type;
+ fid_parms.critical_resource = tbl->critical_resource;
+ fid_parms.resource_hndl = idx;
+ ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
+
+ rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
+ rc);
+ /* Need to free the identifier, so goto error */
+ goto error;
+ }
+
+ return 0;
+error:
+ free_parms.dir = tbl->direction;
+ free_parms.tcam_tbl_type = tbl->resource_type;
+ free_parms.idx = idx;
+ trc = tf_free_tcam_entry(tfp, &free_parms);
+ if (trc)
+ BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
+ tbl->resource_type, tbl->direction, idx);
+ return rc;
+}
+
+static int32_t
+ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct bnxt_ulp_mapper_key_info *kflds;
+ struct ulp_blob key, data;
+ uint32_t i, num_kflds;
+ uint16_t tmplen;
+ struct tf *tfp;
+ struct ulp_flow_db_res_params fid_parms = { 0 };
+ struct tf_insert_em_entry_parms iparms = { 0 };
+ struct tf_delete_em_entry_parms free_parms = { 0 };
+ enum bnxt_ulp_flow_mem_type mtype;
+ struct bnxt_ulp_device_params *dparms = parms->device_params;
+ int32_t trc;
+ int32_t rc = 0;
+ int32_t pad = 0;
+
+ tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
+ rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
+ return -EINVAL;
+ }
+
+ kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
+ if (!kflds || !num_kflds) {
+ BNXT_TF_DBG(ERR, "Failed to get key fields\n");
+ return -EINVAL;
+ }
+
+ /* Initialize the key/result blobs */
+ if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
+ tbl->byte_order) ||
+ !ulp_blob_init(&data, tbl->result_bit_size,
+ tbl->byte_order)) {
+ BNXT_TF_DBG(ERR, "blob inits failed.\n");
+ return -EINVAL;
+ }
+
+ /* create the key */
+ for (i = 0; i < num_kflds; i++) {