xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_mapper.c (revision cf21c2d3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "bnxt.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"
13 #include "bnxt_ulp.h"
14 #include "tfp.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"
19 #include "tf_util.h"
20 #include "ulp_template_db_tbl.h"
21 #include "ulp_port_db.h"
22 #include "ulp_ha_mgr.h"
23 #include "bnxt_tf_pmd_shim.h"
24 
25 static uint8_t mapper_fld_zeros[16] = { 0 };
26 
27 static uint8_t mapper_fld_ones[16] = {
28 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
29 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
30 };
31 
32 static uint8_t mapper_fld_one[16] = {
33 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
34 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
35 };
36 
37 static const char *
ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)38 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
39 {
40 	switch (tmpl_type) {
41 	case BNXT_ULP_TEMPLATE_TYPE_CLASS:
42 		return "class";
43 	case BNXT_ULP_TEMPLATE_TYPE_ACTION:
44 		return "action";
45 	default:
46 		return "invalid template type";
47 	}
48 }
49 
50 static struct bnxt_ulp_glb_resource_info *
ulp_mapper_glb_resource_info_list_get(uint32_t * num_entries)51 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
52 {
53 	if (!num_entries)
54 		return NULL;
55 	*num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
56 	return ulp_glb_resource_tbl;
57 }
58 
59 /*
60  * Read the global resource from the mapper global resource list
61  *
62  * The regval is always returned in big-endian.
63  *
64  * returns 0 on success
65  */
66 static int32_t
ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data * mapper_data,enum tf_dir dir,uint16_t idx,uint64_t * regval,bool * shared)67 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
68 			     enum tf_dir dir,
69 			     uint16_t idx,
70 			     uint64_t *regval,
71 			     bool *shared)
72 {
73 	if (!mapper_data || !regval || !shared ||
74 	    dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
75 		return -EINVAL;
76 
77 	*regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
78 	*shared = mapper_data->glb_res_tbl[dir][idx].shared;
79 	return 0;
80 }
81 
82 /*
83  * Write a global resource to the mapper global resource list
84  *
85  * The regval value must be in big-endian.
86  *
87  * return 0 on success.
88  */
89 static int32_t
ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data * data,struct bnxt_ulp_glb_resource_info * res,uint64_t regval,bool shared)90 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
91 			      struct bnxt_ulp_glb_resource_info *res,
92 			      uint64_t regval, bool shared)
93 {
94 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
95 
96 	/* validate the arguments */
97 	if (!data || res->direction >= TF_DIR_MAX ||
98 	    res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
99 		return -EINVAL;
100 
101 	/* write to the mapper data */
102 	ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
103 	ent->resource_func = res->resource_func;
104 	ent->resource_type = res->resource_type;
105 	ent->resource_hndl = regval;
106 	ent->shared = shared;
107 	return 0;
108 }
109 
110 /*
111  * Internal function to allocate identity resource and store it in mapper data.
112  *
113  * returns 0 on success
114  */
115 static int32_t
ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_data * mapper_data,struct bnxt_ulp_glb_resource_info * glb_res)116 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
117 				   struct bnxt_ulp_mapper_data *mapper_data,
118 				   struct bnxt_ulp_glb_resource_info *glb_res)
119 {
120 	struct tf_alloc_identifier_parms iparms = { 0 };
121 	struct tf_free_identifier_parms fparms;
122 	uint64_t regval;
123 	struct tf *tfp;
124 	int32_t rc = 0;
125 
126 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
127 	if (!tfp)
128 		return -EINVAL;
129 
130 	iparms.ident_type = glb_res->resource_type;
131 	iparms.dir = glb_res->direction;
132 
133 	/* Allocate the Identifier using tf api */
134 	rc = tf_alloc_identifier(tfp, &iparms);
135 	if (rc) {
136 		BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
137 			    tf_dir_2_str(iparms.dir),
138 			    iparms.ident_type);
139 		return rc;
140 	}
141 
142 	/* entries are stored as big-endian format */
143 	regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
144 	/*
145 	 * write to the mapper global resource
146 	 * Shared resources are never allocated through this method, so the
147 	 * shared flag is always false.
148 	 */
149 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
150 	if (rc) {
151 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
152 		/* Free the identifier when update failed */
153 		fparms.dir = iparms.dir;
154 		fparms.ident_type = iparms.ident_type;
155 		fparms.id = iparms.id;
156 		tf_free_identifier(tfp, &fparms);
157 		return rc;
158 	}
159 	return rc;
160 }
161 
162 /*
163  * Internal function to allocate index tbl resource and store it in mapper data.
164  *
165  * returns 0 on success
166  */
167 static int32_t
ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_data * mapper_data,struct bnxt_ulp_glb_resource_info * glb_res)168 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
169 				    struct bnxt_ulp_mapper_data *mapper_data,
170 				    struct bnxt_ulp_glb_resource_info *glb_res)
171 {
172 	struct tf_alloc_tbl_entry_parms	aparms = { 0 };
173 	struct tf_free_tbl_entry_parms	free_parms = { 0 };
174 	uint64_t regval;
175 	struct tf *tfp;
176 	uint32_t tbl_scope_id;
177 	int32_t rc = 0;
178 
179 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
180 	if (!tfp)
181 		return -EINVAL;
182 
183 	/* Get the scope id */
184 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
185 	if (rc) {
186 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
187 		return rc;
188 	}
189 
190 	aparms.type = glb_res->resource_type;
191 	aparms.dir = glb_res->direction;
192 	aparms.tbl_scope_id = tbl_scope_id;
193 
194 	/* Allocate the index tbl using tf api */
195 	rc = tf_alloc_tbl_entry(tfp, &aparms);
196 	if (rc) {
197 		BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n",
198 			    tf_dir_2_str(aparms.dir), aparms.type);
199 		return rc;
200 	}
201 
202 	/* entries are stored as big-endian format */
203 	regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
204 	/*
205 	 * write to the mapper global resource
206 	 * Shared resources are never allocated through this method, so the
207 	 * shared flag is always false.
208 	 */
209 	rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
210 	if (rc) {
211 		BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
212 		/* Free the identifier when update failed */
213 		free_parms.dir = aparms.dir;
214 		free_parms.type = aparms.type;
215 		free_parms.idx = aparms.idx;
216 		tf_free_tbl_entry(tfp, &free_parms);
217 		return rc;
218 	}
219 	return rc;
220 }
221 
222 static int32_t
ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms * parms,uint32_t operand,uint8_t * val)223 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
224 			     uint32_t operand,
225 			     uint8_t *val)
226 {
227 	uint32_t t_idx;
228 
229 	t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT +
230 				  BNXT_ULP_HDR_SIG_ID_SHIFT +
231 				  BNXT_ULP_GLB_FIELD_TBL_SHIFT);
232 	t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
233 				      BNXT_ULP_GLB_FIELD_TBL_SHIFT);
234 	t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
235 		BNXT_ULP_GLB_FIELD_TBL_SHIFT;
236 	t_idx += operand;
237 
238 	if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
239 		BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
240 			    parms->class_tid, t_idx, operand);
241 		*val = 0;
242 		return -EINVAL; /* error */
243 	}
244 	*val = ulp_glb_field_tbl[t_idx];
245 	return 0;
246 }
247 
248 /*
249  * Get the size of the action property for a given index.
250  *
251  * idx [in] The index for the action property
252  *
253  * returns the size of the action property.
254  */
255 static uint32_t
ulp_mapper_act_prop_size_get(uint32_t idx)256 ulp_mapper_act_prop_size_get(uint32_t idx)
257 {
258 	if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
259 		return 0;
260 	return ulp_act_prop_map_table[idx];
261 }
262 
263 static struct bnxt_ulp_mapper_cond_info *
ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms * mparms,uint32_t tid,uint32_t * num_tbls,enum bnxt_ulp_cond_list_opc * opc)264 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
265 				uint32_t tid,
266 				uint32_t *num_tbls,
267 				enum bnxt_ulp_cond_list_opc *opc)
268 {
269 	uint32_t idx;
270 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
271 
272 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
273 	*num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
274 	*opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
275 	idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
276 
277 	return &dev_tbls->cond_list[idx];
278 }
279 
280 static struct bnxt_ulp_mapper_cond_info *
ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl,uint32_t * num_tbls,enum bnxt_ulp_cond_list_opc * opc)281 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
282 				struct bnxt_ulp_mapper_tbl_info *tbl,
283 				uint32_t *num_tbls,
284 				enum bnxt_ulp_cond_list_opc *opc)
285 {
286 	uint32_t idx;
287 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
288 
289 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
290 	*num_tbls = tbl->execute_info.cond_nums;
291 	*opc = tbl->execute_info.cond_list_opcode;
292 	idx = tbl->execute_info.cond_start_idx;
293 
294 	return &dev_tbls->cond_list[idx];
295 }
296 
297 /*
298  * Get a list of classifier tables that implement the flow
299  * Gets a device dependent list of tables that implement the class template id
300  *
301  * mparms [in] The mappers parms with data related to the flow.
302  *
303  * tid [in] The template id that matches the flow
304  *
305  * num_tbls [out] The number of classifier tables in the returned array
306  *
307  * returns An array of classifier tables to implement the flow, or NULL on
308  * error
309  */
310 static struct bnxt_ulp_mapper_tbl_info *
ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms * mparms,uint32_t tid,uint32_t * num_tbls)311 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
312 			uint32_t tid,
313 			uint32_t *num_tbls)
314 {
315 	uint32_t idx;
316 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
317 
318 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
319 
320 	idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
321 	*num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
322 
323 	return &dev_tbls->tbl_list[idx];
324 }
325 
326 /*
327  * Get the list of key fields that implement the flow.
328  *
329  * mparms [in] The mapper parms with information about the flow
330  *
331  * tbl [in] A single table instance to get the key fields from
332  *
333  * num_flds [out] The number of key fields in the returned array
334  *
335  * Returns array of Key fields, or NULL on error.
336  */
337 static struct bnxt_ulp_mapper_key_info *
ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl,uint32_t * num_flds)338 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
339 			  struct bnxt_ulp_mapper_tbl_info *tbl,
340 			  uint32_t *num_flds)
341 {
342 	uint32_t idx;
343 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
344 
345 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
346 	if (!dev_tbls->key_info_list) {
347 		*num_flds = 0;
348 		return NULL;
349 	}
350 
351 	idx		= tbl->key_start_idx;
352 	*num_flds	= tbl->key_num_fields;
353 
354 	return &dev_tbls->key_info_list[idx];
355 }
356 
357 /*
358  * Get the list of data fields that implement the flow.
359  *
360  * mparms [in] The mapper parms with information about the flow
361  *
362  * tbl [in] A single table instance to get the data fields from
363  *
364  * num_flds [out] The number of data fields in the returned array.
365  *
366  * num_encap_flds [out] The number of encap fields in the returned array.
367  *
368  * Returns array of data fields, or NULL on error.
369  */
370 static struct bnxt_ulp_mapper_field_info *
ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl,uint32_t * num_flds,uint32_t * num_encap_flds)371 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
372 			     struct bnxt_ulp_mapper_tbl_info *tbl,
373 			     uint32_t *num_flds,
374 			     uint32_t *num_encap_flds)
375 {
376 	uint32_t idx;
377 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
378 
379 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
380 	if (!dev_tbls->result_field_list) {
381 		*num_flds = 0;
382 		*num_encap_flds = 0;
383 		return NULL;
384 	}
385 
386 	idx		= tbl->result_start_idx;
387 	*num_flds	= tbl->result_num_fields;
388 	*num_encap_flds = tbl->encap_num_fields;
389 
390 	return &dev_tbls->result_field_list[idx];
391 }
392 
393 /*
394  * Get the list of ident fields that implement the flow
395  *
396  * tbl [in] A single table instance to get the ident fields from
397  *
398  * num_flds [out] The number of ident fields in the returned array
399  *
400  * returns array of ident fields, or NULL on error
401  */
402 static struct bnxt_ulp_mapper_ident_info *
ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl,uint32_t * num_flds)403 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
404 			    struct bnxt_ulp_mapper_tbl_info *tbl,
405 			    uint32_t *num_flds)
406 {
407 	uint32_t idx;
408 	const struct bnxt_ulp_template_device_tbls *dev_tbls;
409 
410 	dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
411 	if (!dev_tbls->ident_list) {
412 		*num_flds = 0;
413 		return NULL;
414 	}
415 
416 	idx = tbl->ident_start_idx;
417 	*num_flds = tbl->ident_nums;
418 
419 	return &dev_tbls->ident_list[idx];
420 }
421 
422 static enum tf_tbl_type
ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl,struct ulp_blob * bdata,uint16_t * out_len)423 ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms,
424 			    struct bnxt_ulp_mapper_tbl_info *tbl,
425 			    struct ulp_blob *bdata,
426 			    uint16_t *out_len)
427 {
428 	struct bnxt_ulp_device_params *d_params = mparms->device_params;
429 	uint16_t blob_len = ulp_blob_data_len_get(bdata);
430 	struct bnxt_ulp_dyn_size_map *size_map;
431 	uint32_t i;
432 
433 	if (d_params->dynamic_sram_en) {
434 		switch (tbl->resource_type) {
435 		case TF_TBL_TYPE_ACT_ENCAP_8B:
436 		case TF_TBL_TYPE_ACT_ENCAP_16B:
437 		case TF_TBL_TYPE_ACT_ENCAP_32B:
438 		case TF_TBL_TYPE_ACT_ENCAP_64B:
439 			size_map = d_params->dyn_encap_sizes;
440 			for (i = 0; i < d_params->dyn_encap_list_size; i++) {
441 				if (blob_len <= size_map[i].slab_size) {
442 					*out_len = size_map[i].slab_size;
443 					return size_map[i].tbl_type;
444 				}
445 			}
446 			break;
447 		case TF_TBL_TYPE_ACT_MODIFY_8B:
448 		case TF_TBL_TYPE_ACT_MODIFY_16B:
449 		case TF_TBL_TYPE_ACT_MODIFY_32B:
450 		case TF_TBL_TYPE_ACT_MODIFY_64B:
451 			size_map = d_params->dyn_modify_sizes;
452 			for (i = 0; i < d_params->dyn_modify_list_size; i++) {
453 				if (blob_len <= size_map[i].slab_size) {
454 					*out_len = size_map[i].slab_size;
455 					return size_map[i].tbl_type;
456 				}
457 			}
458 			break;
459 		default:
460 			break;
461 		}
462 	}
463 	return tbl->resource_type;
464 }
465 
466 static uint16_t
ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms * mparms,struct bnxt_ulp_mapper_tbl_info * tbl)467 ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms,
468 			     struct bnxt_ulp_mapper_tbl_info *tbl)
469 {
470 	struct bnxt_ulp_device_params *d_params = mparms->device_params;
471 
472 	if (d_params->dynamic_sram_en) {
473 		switch (tbl->resource_type) {
474 		case TF_TBL_TYPE_ACT_ENCAP_8B:
475 		case TF_TBL_TYPE_ACT_ENCAP_16B:
476 		case TF_TBL_TYPE_ACT_ENCAP_32B:
477 		case TF_TBL_TYPE_ACT_ENCAP_64B:
478 		case TF_TBL_TYPE_ACT_MODIFY_8B:
479 		case TF_TBL_TYPE_ACT_MODIFY_16B:
480 		case TF_TBL_TYPE_ACT_MODIFY_32B:
481 		case TF_TBL_TYPE_ACT_MODIFY_64B:
482 			/* return max size */
483 			return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
484 		default:
485 			break;
486 		}
487 	} else if (tbl->encap_num_fields) {
488 		return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
489 	}
490 	return tbl->result_bit_size;
491 }
492 
493 static inline int32_t
ulp_mapper_tcam_entry_free(struct bnxt_ulp_context * ulp,struct tf * tfp,struct ulp_flow_db_res_params * res)494 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp,
495 			   struct tf *tfp,
496 			   struct ulp_flow_db_res_params *res)
497 {
498 	struct tf_free_tcam_entry_parms fparms = {
499 		.dir		= res->direction,
500 		.tcam_tbl_type	= res->resource_type,
501 		.idx		= (uint16_t)res->resource_hndl
502 	};
503 
504 	/* If HA is enabled, we may have to remap the TF Type */
505 	if (bnxt_ulp_cntxt_ha_enabled(ulp)) {
506 		enum ulp_ha_mgr_region region;
507 		int32_t rc;
508 
509 		switch (res->resource_type) {
510 		case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH:
511 		case TF_TCAM_TBL_TYPE_WC_TCAM_LOW:
512 			rc = ulp_ha_mgr_region_get(ulp, &region);
513 			if (rc)
514 				/* Log this, but assume region is correct */
515 				BNXT_TF_DBG(ERR,
516 					    "Unable to get HA region (%d)\n",
517 					    rc);
518 			else
519 				fparms.tcam_tbl_type =
520 					(region == ULP_HA_REGION_LOW) ?
521 					TF_TCAM_TBL_TYPE_WC_TCAM_LOW :
522 					TF_TCAM_TBL_TYPE_WC_TCAM_HIGH;
523 			break;
524 		default:
525 			break;
526 		}
527 	}
528 	return tf_free_tcam_entry(tfp, &fparms);
529 }
530 
531 static inline int32_t
ulp_mapper_index_entry_free(struct bnxt_ulp_context * ulp,struct tf * tfp,struct ulp_flow_db_res_params * res)532 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
533 			    struct tf *tfp,
534 			    struct ulp_flow_db_res_params *res)
535 {
536 	struct tf_free_tbl_entry_parms fparms = {
537 		.dir	= res->direction,
538 		.type	= res->resource_type,
539 		.idx	= (uint32_t)res->resource_hndl
540 	};
541 
542 	/*
543 	 * Just get the table scope, it will be ignored if not necessary
544 	 * by the tf_free_tbl_entry
545 	 */
546 	(void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
547 
548 	return tf_free_tbl_entry(tfp, &fparms);
549 }
550 
551 static inline int32_t
ulp_mapper_em_entry_free(struct bnxt_ulp_context * ulp,struct tf * tfp,struct ulp_flow_db_res_params * res)552 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
553 			 struct tf *tfp,
554 			 struct ulp_flow_db_res_params *res)
555 {
556 	struct tf_delete_em_entry_parms fparms = { 0 };
557 	int32_t rc;
558 
559 	fparms.dir		= res->direction;
560 	fparms.flow_handle	= res->resource_hndl;
561 
562 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
563 	if (rc) {
564 		BNXT_TF_DBG(ERR, "Failed to get table scope\n");
565 		return -EINVAL;
566 	}
567 
568 	return tf_delete_em_entry(tfp, &fparms);
569 }
570 
571 static inline int32_t
ulp_mapper_ident_free(struct bnxt_ulp_context * ulp __rte_unused,struct tf * tfp,struct ulp_flow_db_res_params * res)572 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
573 		      struct tf *tfp,
574 		      struct ulp_flow_db_res_params *res)
575 {
576 	struct tf_free_identifier_parms fparms = {
577 		.dir		= res->direction,
578 		.ident_type	= res->resource_type,
579 		.id		= (uint16_t)res->resource_hndl
580 	};
581 
582 	return tf_free_identifier(tfp, &fparms);
583 }
584 
585 static inline int32_t
ulp_mapper_mark_free(struct bnxt_ulp_context * ulp,struct ulp_flow_db_res_params * res)586 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
587 		     struct ulp_flow_db_res_params *res)
588 {
589 	return ulp_mark_db_mark_del(ulp,
590 				    res->resource_type,
591 				    res->resource_hndl);
592 }
593 
594 static inline int32_t
ulp_mapper_parent_flow_free(struct bnxt_ulp_context * ulp,uint32_t parent_fid,struct ulp_flow_db_res_params * res)595 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
596 			    uint32_t parent_fid,
597 			    struct ulp_flow_db_res_params *res)
598 {
599 	uint32_t pc_idx;
600 
601 	pc_idx = (uint32_t)res->resource_hndl;
602 
603 	/* reset the child flow bitset*/
604 	if (ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0)) {
605 		BNXT_TF_DBG(ERR, "error in reset parent flow bitset %x:%x\n",
606 			    pc_idx, parent_fid);
607 		return -EINVAL;
608 	}
609 	return 0;
610 }
611 
612 static inline int32_t
ulp_mapper_child_flow_free(struct bnxt_ulp_context * ulp,uint32_t child_fid,struct ulp_flow_db_res_params * res)613 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
614 			   uint32_t child_fid,
615 			   struct ulp_flow_db_res_params *res)
616 {
617 	uint32_t pc_idx;
618 
619 	pc_idx = (uint32_t)res->resource_hndl;
620 
621 	/* reset the child flow bitset*/
622 	if (ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0)) {
623 		BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
624 			    pc_idx, child_fid);
625 		return -EINVAL;
626 	}
627 	return 0;
628 }
629 
630 /*
631  * Process the flow database opcode alloc action.
632  * returns 0 on success
633  */
634 static int32_t
ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)635 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
636 			     struct bnxt_ulp_mapper_tbl_info *tbl)
637 {
638 	uint32_t rid = 0;
639 	uint64_t val64;
640 	int32_t rc = 0;
641 
642 	/* allocate a new fid */
643 	rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
644 				   BNXT_ULP_FDB_TYPE_RID,
645 				   0, &rid);
646 	if (rc) {
647 		BNXT_TF_DBG(ERR,
648 			    "Unable to allocate flow table entry\n");
649 		return -EINVAL;
650 	}
651 	/* Store the allocated fid in regfile*/
652 	val64 = rid;
653 	rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
654 			       tfp_cpu_to_be_64(val64));
655 	if (rc) {
656 		BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
657 			    tbl->fdb_operand);
658 		ulp_flow_db_fid_free(parms->ulp_ctx,
659 				     BNXT_ULP_FDB_TYPE_RID, rid);
660 		return -EINVAL;
661 	}
662 	return 0;
663 }
664 
665 /*
666  * Process the flow database opcode action.
667  * returns 0 on success.
668  */
669 static int32_t
ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,struct ulp_flow_db_res_params * fid_parms)670 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
671 			   struct bnxt_ulp_mapper_tbl_info *tbl,
672 			   struct ulp_flow_db_res_params *fid_parms)
673 {
674 	uint32_t push_fid;
675 	uint64_t val64;
676 	enum bnxt_ulp_fdb_type flow_type;
677 	int32_t rc = 0;
678 
679 	switch (tbl->fdb_opcode) {
680 	case BNXT_ULP_FDB_OPC_PUSH_FID:
681 		push_fid = parms->fid;
682 		flow_type = parms->flow_type;
683 		break;
684 	case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
685 		/* get the fid from the regfile */
686 		rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
687 				      &val64);
688 		if (!rc) {
689 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
690 				    tbl->fdb_operand);
691 			return -EINVAL;
692 		}
693 		/* Use the extracted fid to update the flow resource */
694 		push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
695 		flow_type = BNXT_ULP_FDB_TYPE_RID;
696 		break;
697 	default:
698 		return rc; /* Nothing to be done */
699 	}
700 
701 	/* Add the resource to the flow database */
702 	rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
703 				      push_fid, fid_parms);
704 	if (rc)
705 		BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
706 			    push_fid, rc);
707 	return rc;
708 }
709 
710 /*
711  * Process the flow database opcode action.
712  * returns 0 on success.
713  */
714 static int32_t
ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,uint32_t * priority)715 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
716 				struct bnxt_ulp_mapper_tbl_info *tbl,
717 				uint32_t *priority)
718 {
719 	int32_t rc = 0;
720 
721 	switch (tbl->pri_opcode) {
722 	case BNXT_ULP_PRI_OPC_NOT_USED:
723 		*priority = 0;
724 		break;
725 	case BNXT_ULP_PRI_OPC_CONST:
726 		*priority = tbl->pri_operand;
727 		break;
728 	case BNXT_ULP_PRI_OPC_APP_PRI:
729 		*priority = parms->app_priority;
730 		break;
731 	default:
732 		BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
733 			    tbl->pri_opcode);
734 		rc = -EINVAL;
735 		break;
736 	}
737 	return rc;
738 }
739 
740 /*
741  * Process the identifier list in the given table.
742  * Extract the ident from the table entry and
743  * write it to the reg file.
744  * returns 0 on success.
745  */
746 static int32_t
ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,uint8_t * byte_data,uint32_t byte_data_size,enum bnxt_ulp_byte_order byte_order)747 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
748 			      struct bnxt_ulp_mapper_tbl_info *tbl,
749 			      uint8_t *byte_data,
750 			      uint32_t byte_data_size,
751 			      enum bnxt_ulp_byte_order byte_order)
752 {
753 	struct bnxt_ulp_mapper_ident_info *idents;
754 	uint32_t i, num_idents = 0;
755 	uint64_t val64;
756 
757 	/* validate the null arguments */
758 	if (!byte_data) {
759 		BNXT_TF_DBG(ERR, "invalid argument\n");
760 		return -EINVAL;
761 	}
762 
763 	/* Get the ident list and process each one */
764 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
765 
766 	for (i = 0; i < num_idents; i++) {
767 		/* check the size of the buffer for validation */
768 		if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
769 		    ULP_BYTE_2_BITS(byte_data_size) ||
770 		    idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
771 			BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
772 				    idents[i].ident_bit_pos,
773 				    idents[i].ident_bit_size,
774 				    byte_data_size);
775 			return -EINVAL;
776 		}
777 		val64 = 0;
778 		if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
779 			ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
780 					sizeof(val64),
781 					idents[i].ident_bit_pos,
782 					idents[i].ident_bit_size);
783 		else
784 			ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
785 					idents[i].ident_bit_pos,
786 					idents[i].ident_bit_size);
787 
788 		/* Write it to the regfile, val64 is already in big-endian*/
789 		if (ulp_regfile_write(parms->regfile,
790 				      idents[i].regfile_idx, val64)) {
791 			BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
792 				    idents[i].regfile_idx);
793 			return -EINVAL;
794 		}
795 	}
796 	return 0;
797 }
798 
799 /*
800  * Process the identifier instruction and either store it in the flow database
801  * or return it in the val (if not NULL) on success.  If val is NULL, the
802  * identifier is to be stored in the flow database.
803  */
804 static int32_t
ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,struct bnxt_ulp_mapper_ident_info * ident,uint16_t * val)805 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
806 			 struct bnxt_ulp_mapper_tbl_info *tbl,
807 			 struct bnxt_ulp_mapper_ident_info *ident,
808 			 uint16_t *val)
809 {
810 	struct ulp_flow_db_res_params	fid_parms;
811 	uint64_t id = 0;
812 	int32_t idx;
813 	struct tf_alloc_identifier_parms iparms = { 0 };
814 	struct tf_free_identifier_parms free_parms = { 0 };
815 	struct tf *tfp;
816 	int rc;
817 
818 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
819 	if (!tfp) {
820 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
821 		return -EINVAL;
822 	}
823 
824 	idx = ident->regfile_idx;
825 
826 	iparms.ident_type = ident->ident_type;
827 	iparms.dir = tbl->direction;
828 
829 	rc = tf_alloc_identifier(tfp, &iparms);
830 	if (rc) {
831 		BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
832 			    tf_dir_2_str(iparms.dir),
833 			    tf_ident_2_str(iparms.ident_type));
834 		return rc;
835 	}
836 	BNXT_TF_INF("Alloc ident %s:%s.success.\n",
837 		    tf_dir_2_str(iparms.dir),
838 		    tf_ident_2_str(iparms.ident_type));
839 
840 	id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
841 	if (ulp_regfile_write(parms->regfile, idx, id)) {
842 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
843 		rc = -EINVAL;
844 		/* Need to free the identifier, so goto error */
845 		goto error;
846 	}
847 
848 	/* Link the resource to the flow in the flow db */
849 	if (!val) {
850 		memset(&fid_parms, 0, sizeof(fid_parms));
851 		fid_parms.direction		= tbl->direction;
852 		fid_parms.resource_func	= ident->resource_func;
853 		fid_parms.resource_type	= ident->ident_type;
854 		fid_parms.resource_hndl	= iparms.id;
855 		fid_parms.critical_resource = tbl->critical_resource;
856 		ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
857 
858 		rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
859 		if (rc) {
860 			BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
861 				    rc);
862 			/* Need to free the identifier, so goto error */
863 			goto error;
864 		}
865 	} else {
866 		*val = iparms.id;
867 	}
868 	return 0;
869 
870 error:
871 	/* Need to free the identifier */
872 	free_parms.dir		= tbl->direction;
873 	free_parms.ident_type	= ident->ident_type;
874 	free_parms.id		= iparms.id;
875 
876 	(void)tf_free_identifier(tfp, &free_parms);
877 
878 	BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
879 		    ident->description,
880 		    tf_dir_2_str(tbl->direction));
881 	return rc;
882 }
883 
884 /*
885  * Process the identifier instruction and extract it from result blob.
886  * Increment the identifier reference count and store it in the flow database.
887  */
888 static int32_t
ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,struct bnxt_ulp_mapper_ident_info * ident,struct ulp_blob * res_blob)889 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
890 			 struct bnxt_ulp_mapper_tbl_info *tbl,
891 			 struct bnxt_ulp_mapper_ident_info *ident,
892 			 struct ulp_blob *res_blob)
893 {
894 	struct ulp_flow_db_res_params	fid_parms;
895 	uint64_t id = 0;
896 	uint32_t idx = 0;
897 	struct tf_search_identifier_parms sparms = { 0 };
898 	struct tf_free_identifier_parms free_parms = { 0 };
899 	struct tf *tfp;
900 	int rc;
901 
902 	/* Get the tfp from ulp context */
903 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
904 	if (!tfp) {
905 		BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
906 		return -EINVAL;
907 	}
908 
909 	/* Extract the index from the result blob */
910 	rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
911 			   ident->ident_bit_pos, ident->ident_bit_size);
912 	if (rc) {
913 		BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
914 		return -EIO;
915 	}
916 
917 	/* populate the search params and search identifier shadow table */
918 	sparms.ident_type = ident->ident_type;
919 	sparms.dir = tbl->direction;
920 	/* convert the idx into cpu format */
921 	sparms.search_id = tfp_be_to_cpu_32(idx);
922 
923 	/* Search identifier also increase the reference count */
924 	rc = tf_search_identifier(tfp, &sparms);
925 	if (rc) {
926 		BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
927 			    tf_dir_2_str(sparms.dir),
928 			    tf_ident_2_str(sparms.ident_type),
929 			    sparms.search_id);
930 		return rc;
931 	}
932 	BNXT_TF_INF("Search ident %s:%s:%x.success.\n",
933 		    tf_dir_2_str(sparms.dir),
934 		    tf_tbl_type_2_str(sparms.ident_type),
935 		    sparms.search_id);
936 
937 	/* Write it to the regfile */
938 	id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
939 	if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
940 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
941 		rc = -EINVAL;
942 		/* Need to free the identifier, so goto error */
943 		goto error;
944 	}
945 
946 	/* Link the resource to the flow in the flow db */
947 	memset(&fid_parms, 0, sizeof(fid_parms));
948 	fid_parms.direction = tbl->direction;
949 	fid_parms.resource_func = ident->resource_func;
950 	fid_parms.resource_type = ident->ident_type;
951 	fid_parms.resource_hndl = sparms.search_id;
952 	fid_parms.critical_resource = tbl->critical_resource;
953 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
954 
955 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
956 	if (rc) {
957 		BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
958 			    rc);
959 		/* Need to free the identifier, so goto error */
960 		goto error;
961 	}
962 
963 	return 0;
964 
965 error:
966 	/* Need to free the identifier */
967 	free_parms.dir = tbl->direction;
968 	free_parms.ident_type = ident->ident_type;
969 	free_parms.id = sparms.search_id;
970 	(void)tf_free_identifier(tfp, &free_parms);
971 	BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
972 		    ident->description,
973 		    tf_dir_2_str(tbl->direction), sparms.search_id);
974 	return rc;
975 }
976 
977 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)978 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
979 				 uint32_t port_id,
980 				 uint16_t val16,
981 				 uint8_t **val)
982 {
983 	enum bnxt_ulp_port_table port_data = val16;
984 
985 	switch (port_data) {
986 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
987 		if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
988 						    val)) {
989 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
990 			return -EINVAL;
991 		}
992 		break;
993 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
994 		if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
995 						 val)) {
996 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
997 			return -EINVAL;
998 		}
999 		break;
1000 	case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
1001 		if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
1002 						val)) {
1003 			BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
1004 			return -EINVAL;
1005 		}
1006 		break;
1007 	default:
1008 		BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
1009 		return -EINVAL;
1010 	}
1011 	return 0;
1012 }
1013 
1014 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)1015 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
1016 			     enum bnxt_ulp_field_src field_src,
1017 			     uint8_t *field_opr,
1018 			     enum tf_dir dir,
1019 			     uint8_t is_key,
1020 			     uint32_t bitlen,
1021 			     uint8_t **val,
1022 			     uint32_t *val_len,
1023 			     uint64_t *value)
1024 {
1025 	struct bnxt_ulp_mapper_data *m;
1026 	uint8_t bit;
1027 	uint32_t port_id, val_size, field_size;
1028 	uint16_t idx, size_idx, offset;
1029 	uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
1030 	uint8_t *buffer;
1031 	uint64_t lregval;
1032 	bool shared;
1033 
1034 	*val_len = bitlen;
1035 	*value = 0;
1036 	/* Perform the action */
1037 	switch (field_src) {
1038 	case BNXT_ULP_FIELD_SRC_ZERO:
1039 		*val = mapper_fld_zeros;
1040 		break;
1041 	case BNXT_ULP_FIELD_SRC_CONST:
1042 		*val = field_opr;
1043 		break;
1044 	case BNXT_ULP_FIELD_SRC_ONES:
1045 		*val = mapper_fld_ones;
1046 		*value = 1;
1047 		break;
1048 	case BNXT_ULP_FIELD_SRC_CF:
1049 		if (!ulp_operand_read(field_opr,
1050 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1051 			BNXT_TF_DBG(ERR, "CF operand read failed\n");
1052 			return -EINVAL;
1053 		}
1054 		idx = tfp_be_to_cpu_16(idx);
1055 		if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
1056 			BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1057 				    bytelen);
1058 			return -EINVAL;
1059 		}
1060 		buffer = (uint8_t *)&parms->comp_fld[idx];
1061 		*val = &buffer[sizeof(uint64_t) - bytelen];
1062 		*value = ULP_COMP_FLD_IDX_RD(parms, idx);
1063 		break;
1064 	case BNXT_ULP_FIELD_SRC_RF:
1065 		if (!ulp_operand_read(field_opr,
1066 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1067 			BNXT_TF_DBG(ERR, "RF operand read failed\n");
1068 			return -EINVAL;
1069 		}
1070 
1071 		idx = tfp_be_to_cpu_16(idx);
1072 		/* Uninitialized regfile entries return 0 */
1073 		if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
1074 		    sizeof(uint64_t) < bytelen) {
1075 			BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
1076 				    bytelen);
1077 			return -EINVAL;
1078 		}
1079 		buffer = (uint8_t *)&parms->regfile->entry[idx].data;
1080 		*val = &buffer[sizeof(uint64_t) - bytelen];
1081 		*value = tfp_be_to_cpu_64(lregval);
1082 		break;
1083 	case BNXT_ULP_FIELD_SRC_ACT_PROP:
1084 		if (!ulp_operand_read(field_opr,
1085 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1086 			BNXT_TF_DBG(ERR, "Action operand read failed\n");
1087 			return -EINVAL;
1088 		}
1089 		idx = tfp_be_to_cpu_16(idx);
1090 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1091 			BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
1092 			return -EINVAL;
1093 		}
1094 		buffer = &parms->act_prop->act_details[idx];
1095 		field_size = ulp_mapper_act_prop_size_get(idx);
1096 		if (bytelen > field_size) {
1097 			BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
1098 				    idx, field_size);
1099 			return -EINVAL;
1100 		}
1101 		*val = &buffer[field_size - bytelen];
1102 		break;
1103 	case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1104 		if (!ulp_operand_read(field_opr,
1105 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1106 			BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1107 			return -EINVAL;
1108 		}
1109 		idx = tfp_be_to_cpu_16(idx);
1110 
1111 		if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1112 			BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
1113 			return -EINVAL;
1114 		}
1115 		*val = &parms->act_prop->act_details[idx];
1116 
1117 		/* get the size index next */
1118 		if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1119 				      (uint8_t *)&size_idx, sizeof(uint16_t))) {
1120 			BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1121 			return -EINVAL;
1122 		}
1123 		size_idx = tfp_be_to_cpu_16(size_idx);
1124 		if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1125 			BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1126 			return -EINVAL;
1127 		}
1128 		memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1129 		       sizeof(uint32_t));
1130 		val_size = tfp_be_to_cpu_32(val_size);
1131 		*val_len = ULP_BYTE_2_BITS(val_size);
1132 		break;
1133 	case BNXT_ULP_FIELD_SRC_GLB_RF:
1134 		if (!ulp_operand_read(field_opr,
1135 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1136 			BNXT_TF_DBG(ERR, "Global regfile read failed\n");
1137 			return -EINVAL;
1138 		}
1139 		idx = tfp_be_to_cpu_16(idx);
1140 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
1141 						 dir, idx, &lregval, &shared) ||
1142 		    sizeof(uint64_t) < bytelen) {
1143 			BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
1144 				    idx, bytelen);
1145 			return -EINVAL;
1146 		}
1147 		m = parms->mapper_data;
1148 		buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
1149 		*val = &buffer[sizeof(uint64_t) - bytelen];
1150 		*value = tfp_be_to_cpu_64(lregval);
1151 		break;
1152 	case BNXT_ULP_FIELD_SRC_HF:
1153 	case BNXT_ULP_FIELD_SRC_SUB_HF:
1154 		if (!ulp_operand_read(field_opr,
1155 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1156 			BNXT_TF_DBG(ERR, "Header field read failed\n");
1157 			return -EINVAL;
1158 		}
1159 		idx = tfp_be_to_cpu_16(idx);
1160 		/* get the index from the global field list */
1161 		if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1162 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1163 				    idx);
1164 			return -EINVAL;
1165 		}
1166 		if (is_key)
1167 			buffer = parms->hdr_field[bit].spec;
1168 		else
1169 			buffer = parms->hdr_field[bit].mask;
1170 
1171 		field_size = parms->hdr_field[bit].size;
1172 		if (bytelen > field_size) {
1173 			BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
1174 				    bit, field_size);
1175 			return -EINVAL;
1176 		}
1177 		if (field_src == BNXT_ULP_FIELD_SRC_HF) {
1178 			*val = &buffer[field_size - bytelen];
1179 		} else {
1180 			/* get the offset next */
1181 			if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1182 					      (uint8_t *)&offset,
1183 					      sizeof(uint16_t))) {
1184 				BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
1185 				return -EINVAL;
1186 			}
1187 			offset = tfp_be_to_cpu_16(offset);
1188 			offset = ULP_BITS_2_BYTE_NR(offset);
1189 			if ((offset + bytelen) > field_size) {
1190 				BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
1191 				return -EINVAL;
1192 			}
1193 			*val = &buffer[offset];
1194 		}
1195 		break;
1196 	case BNXT_ULP_FIELD_SRC_HDR_BIT:
1197 		if (!ulp_operand_read(field_opr,
1198 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1199 			BNXT_TF_DBG(ERR, "Header bit read failed\n");
1200 			return -EINVAL;
1201 		}
1202 		lregval = tfp_be_to_cpu_64(lregval);
1203 		if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
1204 			*val = mapper_fld_one;
1205 			*value = 1;
1206 		} else {
1207 			*val = mapper_fld_zeros;
1208 		}
1209 		break;
1210 	case BNXT_ULP_FIELD_SRC_ACT_BIT:
1211 		if (!ulp_operand_read(field_opr,
1212 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1213 			BNXT_TF_DBG(ERR, "Action bit read failed\n");
1214 			return -EINVAL;
1215 		}
1216 		lregval = tfp_be_to_cpu_64(lregval);
1217 		if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
1218 			*val = mapper_fld_one;
1219 			*value = 1;
1220 		} else {
1221 			*val = mapper_fld_zeros;
1222 		}
1223 		break;
1224 	case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1225 		if (!ulp_operand_read(field_opr,
1226 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1227 			BNXT_TF_DBG(ERR, "Field bit read failed\n");
1228 			return -EINVAL;
1229 		}
1230 		idx = tfp_be_to_cpu_16(idx);
1231 		/* get the index from the global field list */
1232 		if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1233 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1234 				    idx);
1235 			return -EINVAL;
1236 		}
1237 		if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
1238 			*val = mapper_fld_one;
1239 			*value = 1;
1240 		} else {
1241 			*val = mapper_fld_zeros;
1242 		}
1243 		break;
1244 	case BNXT_ULP_FIELD_SRC_PORT_TABLE:
1245 		/* The port id is present in the comp field list */
1246 		port_id = ULP_COMP_FLD_IDX_RD(parms,
1247 					      BNXT_ULP_CF_IDX_DEV_PORT_ID);
1248 		/* get the port table enum  */
1249 		if (!ulp_operand_read(field_opr,
1250 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1251 			BNXT_TF_DBG(ERR, "Port table enum read failed\n");
1252 			return -EINVAL;
1253 		}
1254 		idx = tfp_be_to_cpu_16(idx);
1255 		if (ulp_mapper_field_port_db_process(parms, port_id, idx,
1256 						     val)) {
1257 			BNXT_TF_DBG(ERR, "field port table failed\n");
1258 			return -EINVAL;
1259 		}
1260 		break;
1261 	case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT:
1262 		if (!ulp_operand_read(field_opr,
1263 				      (uint8_t *)&lregval, sizeof(uint64_t))) {
1264 			BNXT_TF_DBG(ERR, "Header bit read failed\n");
1265 			return -EINVAL;
1266 		}
1267 		lregval = tfp_be_to_cpu_64(lregval);
1268 		if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) {
1269 			*val = mapper_fld_one;
1270 			*value = 1;
1271 		} else {
1272 			*val = mapper_fld_zeros;
1273 		}
1274 		break;
1275 	case BNXT_ULP_FIELD_SRC_ENC_FIELD:
1276 		if (!ulp_operand_read(field_opr,
1277 				      (uint8_t *)&idx, sizeof(uint16_t))) {
1278 			BNXT_TF_DBG(ERR, "Header field read failed\n");
1279 			return -EINVAL;
1280 		}
1281 		idx = tfp_be_to_cpu_16(idx);
1282 		/* get the index from the global field list */
1283 		if (idx >= BNXT_ULP_ENC_FIELD_LAST) {
1284 			BNXT_TF_DBG(ERR, "invalid encap field tbl idx %d\n",
1285 				    idx);
1286 			return -EINVAL;
1287 		}
1288 		buffer = parms->enc_field[idx].spec;
1289 		field_size = parms->enc_field[idx].size;
1290 		if (bytelen > field_size) {
1291 			BNXT_TF_DBG(ERR, "Encap field[%d] size small %u\n",
1292 				    idx, field_size);
1293 			return -EINVAL;
1294 		}
1295 		*val = &buffer[field_size - bytelen];
1296 		break;
1297 	case BNXT_ULP_FIELD_SRC_SKIP:
1298 		/* do nothing */
1299 		*val = mapper_fld_zeros;
1300 		*val_len = 0;
1301 		break;
1302 	case BNXT_ULP_FIELD_SRC_REJECT:
1303 		return -EINVAL;
1304 	default:
1305 		BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
1306 		return -EINVAL;
1307 	}
1308 	return 0;
1309 }
1310 
ulp_mapper_field_buffer_eval(uint8_t * buffer,uint32_t bitlen,uint64_t * output)1311 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
1312 					    uint64_t *output)
1313 {
1314 	uint16_t val_16;
1315 	uint32_t val_32;
1316 	uint64_t val_64;
1317 	uint32_t bytelen;
1318 
1319 	bytelen = ULP_BITS_2_BYTE(bitlen);
1320 	if (bytelen == sizeof(uint8_t)) {
1321 		*output = *((uint8_t *)buffer);
1322 	} else if (bytelen == sizeof(uint16_t)) {
1323 		val_16 = *((uint16_t *)buffer);
1324 		*output =  tfp_be_to_cpu_16(val_16);
1325 	} else if (bytelen == sizeof(uint32_t)) {
1326 		val_32 = *((uint32_t *)buffer);
1327 		*output =  tfp_be_to_cpu_32(val_32);
1328 	} else if (bytelen == sizeof(val_64)) {
1329 		val_64 = *((uint64_t *)buffer);
1330 		*output =  tfp_be_to_cpu_64(val_64);
1331 	} else {
1332 		*output = 0;
1333 		return -EINVAL;
1334 	}
1335 	return 0;
1336 }
1337 
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)1338 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
1339 					   struct ulp_blob *blob,
1340 					   uint8_t *val,
1341 					   uint32_t val_len,
1342 					   uint8_t **out_val)
1343 {
1344 	if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
1345 		if (ulp_blob_pad_push(blob, val_len) < 0) {
1346 			BNXT_TF_DBG(ERR, "too large for blob\n");
1347 			return -EINVAL;
1348 		}
1349 	} else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
1350 		if (ulp_blob_push_encap(blob, val, val_len) < 0) {
1351 			BNXT_TF_DBG(ERR, "encap blob push failed\n");
1352 			return -EINVAL;
1353 		}
1354 	} else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) {
1355 		/* do nothing */
1356 	} else {
1357 		if (!ulp_blob_push(blob, val, val_len)) {
1358 			BNXT_TF_DBG(ERR, "push of val1 failed\n");
1359 			return -EINVAL;
1360 		}
1361 	}
1362 	*out_val = val;
1363 	return 0;
1364 }
1365 
1366 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)1367 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
1368 			     enum tf_dir dir,
1369 			     struct bnxt_ulp_mapper_field_info *fld,
1370 			     struct ulp_blob *blob,
1371 			     uint8_t is_key,
1372 			     const char *name)
1373 {
1374 	uint16_t write_idx = blob->write_idx;
1375 	uint8_t *val = NULL, *val1, *val2, *val3;
1376 	uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
1377 	uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
1378 	uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
1379 	uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
1380 	uint64_t value1 = 0, value2 = 0, value3 = 0;
1381 	int32_t rc = 0;
1382 
1383 	/* prepare the field source and values */
1384 	switch (fld->field_opc) {
1385 	case BNXT_ULP_FIELD_OPC_SRC1:
1386 		process_src1 = 1;
1387 		break;
1388 	case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1389 		process_src1 = 1;
1390 		break;
1391 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1392 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1393 		process_src3 = 1;
1394 		eval_src3 = 1;
1395 		process_src1 = 1;
1396 		process_src2 = 1;
1397 		eval_src1 = 1;
1398 		eval_src2 = 1;
1399 		break;
1400 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1401 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1402 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1403 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1404 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1405 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1406 		process_src1 = 1;
1407 		process_src2 = 1;
1408 		eval_src1 = 1;
1409 		eval_src2 = 1;
1410 		break;
1411 	default:
1412 		break;
1413 	}
1414 
1415 	/* process the src1 opcode  */
1416 	if (process_src1) {
1417 		if (ulp_mapper_field_src_process(parms, fld->field_src1,
1418 						 fld->field_opr1, dir, is_key,
1419 						 fld->field_bit_size, &val1,
1420 						 &val1_len, &value1)) {
1421 			BNXT_TF_DBG(ERR, "fld src1 process failed\n");
1422 			goto error;
1423 		}
1424 		if (eval_src1) {
1425 			if (ulp_mapper_field_buffer_eval(val1, val1_len,
1426 							 &val1_int)) {
1427 				BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
1428 				goto error;
1429 			}
1430 		}
1431 	}
1432 
1433 	/* for "if then clause" set the correct process  */
1434 	if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
1435 		if (value1)
1436 			process_src2 = 1;
1437 		else
1438 			process_src3 = 1;
1439 	}
1440 
1441 	/* process src2 opcode */
1442 	if (process_src2) {
1443 		if (ulp_mapper_field_src_process(parms, fld->field_src2,
1444 						 fld->field_opr2, dir, is_key,
1445 						 fld->field_bit_size, &val2,
1446 						 &val2_len, &value2)) {
1447 			BNXT_TF_DBG(ERR, "fld src2 process failed\n");
1448 			goto error;
1449 		}
1450 		if (eval_src2) {
1451 			if (ulp_mapper_field_buffer_eval(val2, val2_len,
1452 							 &val2_int)) {
1453 				BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
1454 				goto error;
1455 			}
1456 		}
1457 	}
1458 
1459 	/* process src3 opcode */
1460 	if (process_src3) {
1461 		if (ulp_mapper_field_src_process(parms, fld->field_src3,
1462 						 fld->field_opr3, dir, is_key,
1463 						 fld->field_bit_size, &val3,
1464 						 &val3_len, &value3)) {
1465 			BNXT_TF_DBG(ERR, "fld src3 process failed\n");
1466 			goto error;
1467 		}
1468 		if (eval_src3) {
1469 			if (ulp_mapper_field_buffer_eval(val3, val3_len,
1470 							 &val3_int)) {
1471 				BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
1472 				goto error;
1473 			}
1474 		}
1475 	}
1476 
1477 	val_len = fld->field_bit_size;
1478 	/* process the field opcodes */
1479 	switch (fld->field_opc) {
1480 	case BNXT_ULP_FIELD_OPC_SRC1:
1481 		rc = ulp_mapper_field_blob_write(fld->field_src1,
1482 						 blob, val1, val1_len, &val);
1483 		val_len = val1_len;
1484 		break;
1485 	case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1486 		if (value1) {
1487 			rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
1488 							 val2, val2_len, &val);
1489 			val_len = val2_len;
1490 		} else {
1491 			rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
1492 							 val3, val3_len, &val);
1493 			val_len = val3_len;
1494 		}
1495 		break;
1496 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1497 	case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1498 		val_int = val1_int + val2_int;
1499 		val_int = tfp_cpu_to_be_64(val_int);
1500 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1501 		if (!val)
1502 			rc = -EINVAL;
1503 		break;
1504 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1505 	case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1506 		val_int = val1_int - val2_int;
1507 		val_int = tfp_cpu_to_be_64(val_int);
1508 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1509 		if (!val)
1510 			rc = -EINVAL;
1511 		break;
1512 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1513 		val_int = val1_int | val2_int;
1514 		val_int = tfp_cpu_to_be_64(val_int);
1515 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1516 		if (!val)
1517 			rc = -EINVAL;
1518 		break;
1519 	case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1520 		val_int = val1_int | val2_int | val3_int;
1521 		val_int = tfp_cpu_to_be_64(val_int);
1522 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1523 		if (!val)
1524 			rc = -EINVAL;
1525 		break;
1526 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1527 		val_int = val1_int & val2_int;
1528 		val_int = tfp_cpu_to_be_64(val_int);
1529 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1530 		if (!val)
1531 			rc = -EINVAL;
1532 		break;
1533 	case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1534 		val_int = val1_int & (val2_int | val3_int);
1535 		val_int = tfp_cpu_to_be_64(val_int);
1536 		val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1537 		if (!val)
1538 			rc = -EINVAL;
1539 		break;
1540 	case BNXT_ULP_FIELD_OPC_SKIP:
1541 		break;
1542 	default:
1543 		BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
1544 		rc = -EINVAL;
1545 		break;
1546 	}
1547 
1548 	if (!rc) {
1549 		return rc;
1550 	}
1551 error:
1552 	BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
1553 		    fld->description, (val) ? write_idx : 0, val_len);
1554 	return -EINVAL;
1555 }
1556 
1557 /*
1558  * Result table process and fill the result blob.
1559  * data [out] - the result blob data
1560  */
1561 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)1562 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1563 			    struct bnxt_ulp_mapper_tbl_info *tbl,
1564 			    struct ulp_blob *data,
1565 			    const char *name)
1566 {
1567 	struct bnxt_ulp_mapper_field_info *dflds;
1568 	uint32_t i = 0, num_flds = 0, encap_flds = 0;
1569 	struct ulp_blob encap_blob;
1570 	int32_t rc = 0;
1571 
1572 	/* Get the result field list */
1573 	dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1574 					     &encap_flds);
1575 
1576 	/* validate the result field list counts */
1577 	if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1578 	     (!num_flds && !encap_flds)) || !dflds ||
1579 	    (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1580 		(!num_flds || encap_flds))) {
1581 		BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1582 			    num_flds, encap_flds);
1583 		return -EINVAL;
1584 	}
1585 
1586 	/* process the result fields */
1587 	for (i = 0; i < num_flds; i++) {
1588 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1589 						  &dflds[i], data, 0, name);
1590 		if (rc) {
1591 			BNXT_TF_DBG(ERR, "result field processing failed\n");
1592 			return rc;
1593 		}
1594 	}
1595 
1596 	/* process encap fields if any */
1597 	if (encap_flds) {
1598 		uint32_t pad = 0;
1599 		/* Initialize the encap blob */
1600 		if (!tbl->record_size &&
1601 		    !parms->device_params->dynamic_sram_en) {
1602 			BNXT_TF_DBG(ERR, "Encap tbl record size incorrect\n");
1603 			return -EINVAL;
1604 		}
1605 		if (!ulp_blob_init(&encap_blob,
1606 				   ULP_BYTE_2_BITS(tbl->record_size),
1607 				   parms->device_params->encap_byte_order)) {
1608 			BNXT_TF_DBG(ERR, "blob inits failed.\n");
1609 			return -EINVAL;
1610 		}
1611 		for (; i < encap_flds; i++) {
1612 			rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1613 							  &dflds[i],
1614 							  &encap_blob, 0, name);
1615 			if (rc) {
1616 				BNXT_TF_DBG(ERR,
1617 					    "encap field processing failed\n");
1618 				return rc;
1619 			}
1620 		}
1621 		/* add the dynamic pad push */
1622 		if (parms->device_params->dynamic_sram_en) {
1623 			uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size);
1624 
1625 			(void)ulp_mapper_dyn_tbl_type_get(parms, tbl,
1626 							  &encap_blob, &rec_s);
1627 			pad = rec_s - ulp_blob_data_len_get(&encap_blob);
1628 		} else {
1629 			pad = ULP_BYTE_2_BITS(tbl->record_size) -
1630 				ulp_blob_data_len_get(&encap_blob);
1631 		}
1632 		if (ulp_blob_pad_push(&encap_blob, pad) < 0) {
1633 			BNXT_TF_DBG(ERR, "encap buffer padding failed\n");
1634 			return -EINVAL;
1635 		}
1636 
1637 
1638 		/* perform the 64 bit byte swap */
1639 		ulp_blob_perform_64B_byte_swap(&encap_blob);
1640 		/* Append encap blob to the result blob */
1641 		rc = ulp_blob_buffer_copy(data, &encap_blob);
1642 		if (rc) {
1643 			BNXT_TF_DBG(ERR, "encap buffer copy failed\n");
1644 			return rc;
1645 		}
1646 	}
1647 	return rc;
1648 }
1649 
1650 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)1651 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1652 			     struct bnxt_ulp_mapper_tbl_info *tbl,
1653 			     uint64_t flow_id)
1654 {
1655 	struct ulp_flow_db_res_params fid_parms;
1656 	uint32_t mark, gfid, mark_flag;
1657 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1658 	int32_t rc = 0;
1659 
1660 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1661 	    !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1662 	     ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1663 			      BNXT_ULP_ACT_BIT_MARK)))
1664 		return rc; /* no need to perform gfid process */
1665 
1666 	/* Get the mark id details from action property */
1667 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1668 	       sizeof(mark));
1669 	mark = tfp_be_to_cpu_32(mark);
1670 
1671 	TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1672 	mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1673 
1674 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1675 				  gfid, mark);
1676 	if (rc) {
1677 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1678 		return rc;
1679 	}
1680 	fid_parms.direction = tbl->direction;
1681 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1682 	fid_parms.critical_resource = tbl->critical_resource;
1683 	fid_parms.resource_type	= mark_flag;
1684 	fid_parms.resource_hndl	= gfid;
1685 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1686 
1687 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1688 	if (rc)
1689 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1690 	return rc;
1691 }
1692 
1693 static int32_t
ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)1694 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1695 				struct bnxt_ulp_mapper_tbl_info *tbl)
1696 {
1697 	struct ulp_flow_db_res_params fid_parms;
1698 	uint32_t act_idx, mark, mark_flag;
1699 	uint64_t val64;
1700 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1701 	int32_t rc = 0;
1702 
1703 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1704 	    !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1705 	     ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1706 			      BNXT_ULP_ACT_BIT_MARK)))
1707 		return rc; /* no need to perform mark action process */
1708 
1709 	/* Get the mark id details from action property */
1710 	memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1711 	       sizeof(mark));
1712 	mark = tfp_be_to_cpu_32(mark);
1713 
1714 	if (!ulp_regfile_read(parms->regfile,
1715 			      BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1716 			      &val64)) {
1717 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1718 		return -EINVAL;
1719 	}
1720 	act_idx = tfp_be_to_cpu_64(val64);
1721 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1722 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1723 				  act_idx, mark);
1724 	if (rc) {
1725 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1726 		return rc;
1727 	}
1728 	fid_parms.direction = tbl->direction;
1729 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1730 	fid_parms.critical_resource = tbl->critical_resource;
1731 	fid_parms.resource_type	= mark_flag;
1732 	fid_parms.resource_hndl	= act_idx;
1733 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1734 
1735 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1736 	if (rc)
1737 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1738 	return rc;
1739 }
1740 
1741 static int32_t
ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)1742 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1743 				struct bnxt_ulp_mapper_tbl_info *tbl)
1744 {
1745 	struct ulp_flow_db_res_params fid_parms;
1746 	uint32_t act_idx, mark, mark_flag;
1747 	uint64_t val64;
1748 	enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1749 	int32_t rc = 0;
1750 
1751 	if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1752 	    mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1753 		return rc; /* no need to perform mark action process */
1754 
1755 	/* Get the mark id details from the computed field of dev port id */
1756 	mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1757 
1758 	 /* Get the main action pointer */
1759 	if (!ulp_regfile_read(parms->regfile,
1760 			      BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1761 			      &val64)) {
1762 		BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1763 		return -EINVAL;
1764 	}
1765 	act_idx = tfp_be_to_cpu_64(val64);
1766 
1767 	/* Set the mark flag to local fid and vfr flag */
1768 	mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1769 
1770 	rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1771 				  act_idx, mark);
1772 	if (rc) {
1773 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1774 		return rc;
1775 	}
1776 	fid_parms.direction = tbl->direction;
1777 	fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1778 	fid_parms.critical_resource = tbl->critical_resource;
1779 	fid_parms.resource_type	= mark_flag;
1780 	fid_parms.resource_hndl	= act_idx;
1781 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1782 
1783 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1784 	if (rc)
1785 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1786 	return rc;
1787 }
1788 
1789 /* Tcam table scan the identifier list and allocate each identifier */
1790 static int32_t
ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)1791 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1792 				     struct bnxt_ulp_mapper_tbl_info *tbl)
1793 {
1794 	struct bnxt_ulp_mapper_ident_info *idents;
1795 	uint32_t num_idents;
1796 	uint32_t i;
1797 
1798 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1799 	for (i = 0; i < num_idents; i++) {
1800 		if (ulp_mapper_ident_process(parms, tbl,
1801 					     &idents[i], NULL))
1802 			return -EINVAL;
1803 	}
1804 	return 0;
1805 }
1806 
1807 /*
1808  * Tcam table scan the identifier list and extract the identifier from
1809  * the result blob.
1810  */
1811 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)1812 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1813 				       struct bnxt_ulp_mapper_tbl_info *tbl,
1814 				       struct ulp_blob *data)
1815 {
1816 	struct bnxt_ulp_mapper_ident_info *idents;
1817 	uint32_t num_idents = 0, i;
1818 	int32_t rc = 0;
1819 
1820 	/*
1821 	 * Extract the listed identifiers from the result field,
1822 	 * no need to allocate them.
1823 	 */
1824 	idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1825 	for (i = 0; i < num_idents; i++) {
1826 		rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1827 		if (rc) {
1828 			BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1829 			return rc;
1830 		}
1831 	}
1832 	return rc;
1833 }
1834 
1835 /* Internal function to write the tcam entry */
1836 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)1837 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1838 				struct bnxt_ulp_mapper_tbl_info *tbl,
1839 				struct ulp_blob *key,
1840 				struct ulp_blob *mask,
1841 				struct ulp_blob *data,
1842 				uint16_t idx)
1843 {
1844 	struct tf_set_tcam_entry_parms sparms = { 0 };
1845 	struct tf *tfp;
1846 	uint16_t tmplen;
1847 	int32_t rc;
1848 
1849 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1850 	if (!tfp) {
1851 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1852 		return -EINVAL;
1853 	}
1854 
1855 	sparms.dir		= tbl->direction;
1856 	sparms.tcam_tbl_type	= tbl->resource_type;
1857 	sparms.idx		= idx;
1858 	sparms.key		= ulp_blob_data_get(key, &tmplen);
1859 	sparms.key_sz_in_bits	= tmplen;
1860 	sparms.mask		= ulp_blob_data_get(mask, &tmplen);
1861 	sparms.result		= ulp_blob_data_get(data, &tmplen);
1862 	sparms.result_sz_in_bits = tmplen;
1863 	if (tf_set_tcam_entry(tfp, &sparms)) {
1864 		BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1865 			    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1866 			    tf_dir_2_str(sparms.dir), sparms.idx);
1867 		return -EIO;
1868 	}
1869 	BNXT_TF_INF("tcam[%s][%s][%x] write success.\n",
1870 		    tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1871 		    tf_dir_2_str(sparms.dir), sparms.idx);
1872 
1873 	/* Mark action */
1874 	rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1875 	if (rc) {
1876 		BNXT_TF_DBG(ERR, "failed mark action processing\n");
1877 		return rc;
1878 	}
1879 
1880 	return rc;
1881 }
1882 
1883 /*
1884  * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1885  *
1886  * parms [in] The mappers parms with data related to the flow.
1887  *
1888  * key [in] The original key to be transformed
1889  *
1890  * mask [in] The original mask to be transformed
1891  *
1892  * tkey [in/out] The transformed key
1893  *
1894  * tmask [in/out] The transformed mask
1895  *
1896  * returns zero on success, non-zero on failure
1897  */
1898 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)1899 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1900 					struct ulp_blob *key,
1901 					struct ulp_blob *mask,
1902 					struct ulp_blob *tkey,
1903 					struct ulp_blob *tmask)
1904 {
1905 	uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1906 	uint32_t cword, i, rc;
1907 	int32_t pad;
1908 	uint8_t *val;
1909 
1910 	slice_width = dparms->wc_slice_width;
1911 	clen = dparms->wc_ctl_size_bits;
1912 	max_slices = dparms->wc_max_slices;
1913 	blen = ulp_blob_data_len_get(key);
1914 
1915 	/* Get the length of the key based on number of slices and width */
1916 	num_slices = 1;
1917 	tlen = slice_width;
1918 	while (tlen < blen &&
1919 	       num_slices <= max_slices) {
1920 		num_slices = num_slices << 1;
1921 		tlen = tlen << 1;
1922 	}
1923 
1924 	if (num_slices > max_slices) {
1925 		BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
1926 		return -EINVAL;
1927 	}
1928 
1929 	/* The key/mask may not be on a natural slice boundary, pad it */
1930 	pad = tlen - blen;
1931 	if (ulp_blob_pad_push(key, pad) < 0 ||
1932 	    ulp_blob_pad_push(mask, pad) < 0) {
1933 		BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
1934 		return -EINVAL;
1935 	}
1936 
1937 	/* The new length accounts for the ctrl word length and num slices */
1938 	tlen = tlen + clen * num_slices;
1939 	if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
1940 	    !ulp_blob_init(tmask, tlen, mask->byte_order)) {
1941 		BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
1942 		return -EINVAL;
1943 	}
1944 
1945 	/* Build the transformed key/mask */
1946 	cword = dparms->wc_mode_list[num_slices - 1];
1947 	cword = tfp_cpu_to_be_32(cword);
1948 	offset = 0;
1949 	for (i = 0; i < num_slices; i++) {
1950 		val = ulp_blob_push_32(tkey, &cword, clen);
1951 		if (!val) {
1952 			BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
1953 			return -EINVAL;
1954 		}
1955 		val = ulp_blob_push_32(tmask, &cword, clen);
1956 		if (!val) {
1957 			BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
1958 			return -EINVAL;
1959 		}
1960 		rc = ulp_blob_append(tkey, key, offset, slice_width);
1961 		if (rc) {
1962 			BNXT_TF_DBG(ERR, "Key blob append failed\n");
1963 			return rc;
1964 		}
1965 		rc = ulp_blob_append(tmask, mask, offset, slice_width);
1966 		if (rc) {
1967 			BNXT_TF_DBG(ERR, "Mask blob append failed\n");
1968 			return rc;
1969 		}
1970 		offset += slice_width;
1971 	}
1972 
1973 	/* The key/mask are byte reversed on every 4 byte chunk */
1974 	ulp_blob_perform_byte_reverse(tkey, 4);
1975 	ulp_blob_perform_byte_reverse(tmask, 4);
1976 
1977 	return 0;
1978 }
1979 
1980 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob * blob)1981 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1982 {
1983 	ulp_blob_perform_64B_word_swap(blob);
1984 	ulp_blob_perform_64B_byte_swap(blob);
1985 }
1986 
ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info * tbl)1987 static int32_t ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl)
1988 {
1989 	if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
1990 	    tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
1991 	    tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW)
1992 		return 1;
1993 	return 0;
1994 }
1995 
1996 static int32_t
ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)1997 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1998 			    struct bnxt_ulp_mapper_tbl_info *tbl)
1999 {
2000 	struct bnxt_ulp_mapper_key_info	*kflds;
2001 	struct ulp_blob okey, omask, data, update_data;
2002 	struct ulp_blob tkey, tmask; /* transform key and mask */
2003 	struct ulp_blob *key, *mask;
2004 	uint32_t i, num_kflds;
2005 	struct tf *tfp;
2006 	int32_t rc, trc;
2007 	struct bnxt_ulp_device_params *dparms = parms->device_params;
2008 	struct tf_alloc_tcam_entry_parms aparms		= { 0 };
2009 	struct tf_search_tcam_entry_parms searchparms   = { 0 };
2010 	struct ulp_flow_db_res_params	fid_parms	= { 0 };
2011 	struct tf_free_tcam_entry_parms free_parms	= { 0 };
2012 	uint32_t hit = 0;
2013 	uint16_t tmplen = 0;
2014 	uint16_t idx;
2015 	enum bnxt_ulp_byte_order key_byte_order;
2016 
2017 	/* Set the key and mask to the original key and mask. */
2018 	key = &okey;
2019 	mask = &omask;
2020 
2021 	/* Skip this if table opcode is NOP */
2022 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
2023 	    tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
2024 		BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
2025 			    tbl->tbl_opcode);
2026 		return 0;
2027 	}
2028 
2029 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2030 	if (!tfp) {
2031 		BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
2032 		return -EINVAL;
2033 	}
2034 
2035 	/* If only allocation of identifier then perform and exit */
2036 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) {
2037 		rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2038 		return rc;
2039 	}
2040 
2041 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2042 	if (!kflds || !num_kflds) {
2043 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2044 		return -EINVAL;
2045 	}
2046 
2047 	if (ulp_mapper_tcam_is_wc_tcam(tbl))
2048 		key_byte_order = dparms->wc_key_byte_order;
2049 	else
2050 		key_byte_order = dparms->key_byte_order;
2051 
2052 	if (!ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) ||
2053 	    !ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) ||
2054 	    !ulp_blob_init(&data, tbl->result_bit_size,
2055 			   dparms->result_byte_order) ||
2056 	    !ulp_blob_init(&update_data, tbl->result_bit_size,
2057 			   dparms->result_byte_order)) {
2058 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
2059 		return -EINVAL;
2060 	}
2061 
2062 	/* create the key/mask */
2063 	/*
2064 	 * NOTE: The WC table will require some kind of flag to handle the
2065 	 * mode bits within the key/mask
2066 	 */
2067 	for (i = 0; i < num_kflds; i++) {
2068 		/* Setup the key */
2069 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2070 						  &kflds[i].field_info_spec,
2071 						  key, 1, "TCAM Key");
2072 		if (rc) {
2073 			BNXT_TF_DBG(ERR, "Key field set failed %s\n",
2074 				    kflds[i].field_info_spec.description);
2075 			return rc;
2076 		}
2077 
2078 		/* Setup the mask */
2079 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2080 						  &kflds[i].field_info_mask,
2081 						  mask, 0, "TCAM Mask");
2082 		if (rc) {
2083 			BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
2084 				    kflds[i].field_info_mask.description);
2085 			return rc;
2086 		}
2087 	}
2088 
2089 	/* For wild card tcam perform the post process to swap the blob */
2090 	if (ulp_mapper_tcam_is_wc_tcam(tbl)) {
2091 		if (dparms->dynamic_pad_en) {
2092 			/* Sets up the slices for writing to the WC TCAM */
2093 			rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
2094 								     key, mask,
2095 								     &tkey,
2096 								     &tmask);
2097 			if (rc) {
2098 				BNXT_TF_DBG(ERR,
2099 					    "Failed to post proc WC entry.\n");
2100 				return rc;
2101 			}
2102 			/* Now need to use the transform Key/Mask */
2103 			key = &tkey;
2104 			mask = &tmask;
2105 		} else {
2106 			ulp_mapper_wc_tcam_tbl_post_process(key);
2107 			ulp_mapper_wc_tcam_tbl_post_process(mask);
2108 		}
2109 
2110 	}
2111 
2112 	if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2113 		/* allocate the tcam index */
2114 		aparms.dir = tbl->direction;
2115 		aparms.tcam_tbl_type = tbl->resource_type;
2116 		aparms.key = ulp_blob_data_get(key, &tmplen);
2117 		aparms.key_sz_in_bits = tmplen;
2118 		aparms.mask = ulp_blob_data_get(mask, &tmplen);
2119 
2120 		/* calculate the entry priority */
2121 		rc = ulp_mapper_priority_opc_process(parms, tbl,
2122 						     &aparms.priority);
2123 		if (rc) {
2124 			BNXT_TF_DBG(ERR, "entry priority process failed\n");
2125 			return rc;
2126 		}
2127 
2128 		rc = tf_alloc_tcam_entry(tfp, &aparms);
2129 		if (rc) {
2130 			BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
2131 			return rc;
2132 		}
2133 		idx = aparms.idx;
2134 		hit = aparms.hit;
2135 	} else {
2136 		/*
2137 		 * Searching before allocation to see if we already have an
2138 		 * entry.  This allows re-use of a constrained resource.
2139 		 */
2140 		searchparms.dir = tbl->direction;
2141 		searchparms.tcam_tbl_type = tbl->resource_type;
2142 		searchparms.key = ulp_blob_data_get(key, &tmplen);
2143 		searchparms.key_sz_in_bits = tbl->key_bit_size;
2144 		searchparms.mask = ulp_blob_data_get(mask, &tmplen);
2145 		searchparms.alloc = 1;
2146 		searchparms.result = ulp_blob_data_get(&data, &tmplen);
2147 		searchparms.result_sz_in_bits = tbl->result_bit_size;
2148 
2149 		/* calculate the entry priority */
2150 		rc = ulp_mapper_priority_opc_process(parms, tbl,
2151 						     &searchparms.priority);
2152 		if (rc) {
2153 			BNXT_TF_DBG(ERR, "entry priority process failed\n");
2154 			return rc;
2155 		}
2156 
2157 		rc = tf_search_tcam_entry(tfp, &searchparms);
2158 		if (rc) {
2159 			BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
2160 			return rc;
2161 		}
2162 
2163 		/* Successful search, check the result */
2164 		if (searchparms.search_status == REJECT) {
2165 			BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
2166 			return -ENOMEM;
2167 		}
2168 		idx = searchparms.idx;
2169 		hit = searchparms.hit;
2170 	}
2171 
2172 	/* Write the tcam index into the regfile*/
2173 	if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
2174 			      (uint64_t)tfp_cpu_to_be_64(idx))) {
2175 		BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2176 			    tbl->tbl_operand);
2177 		rc = -EINVAL;
2178 		/* Need to free the tcam idx, so goto error */
2179 		goto error;
2180 	}
2181 
2182 	/* if it is miss then it is same as no search before alloc */
2183 	if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2184 		/*Scan identifier list, allocate identifier and update regfile*/
2185 		rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2186 		/* Create the result blob */
2187 		if (!rc)
2188 			rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2189 							 "TCAM Result");
2190 		/* write the tcam entry */
2191 		if (!rc)
2192 			rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
2193 							     mask, &data, idx);
2194 	} else {
2195 		/*Scan identifier list, extract identifier and update regfile*/
2196 		rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2197 	}
2198 	if (rc)
2199 		goto error;
2200 
2201 	/* Add the tcam index to the flow database */
2202 	fid_parms.direction = tbl->direction;
2203 	fid_parms.resource_func	= tbl->resource_func;
2204 	fid_parms.resource_type	= tbl->resource_type;
2205 	fid_parms.critical_resource = tbl->critical_resource;
2206 	fid_parms.resource_hndl	= idx;
2207 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2208 
2209 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2210 	if (rc) {
2211 		BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2212 			    rc);
2213 		/* Need to free the identifier, so goto error */
2214 		goto error;
2215 	}
2216 
2217 	return 0;
2218 error:
2219 	free_parms.dir			= tbl->direction;
2220 	free_parms.tcam_tbl_type	= tbl->resource_type;
2221 	free_parms.idx			= idx;
2222 	trc = tf_free_tcam_entry(tfp, &free_parms);
2223 	if (trc)
2224 		BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2225 			    tbl->resource_type, tbl->direction, idx);
2226 	return rc;
2227 }
2228 
2229 static int32_t
ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)2230 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2231 			  struct bnxt_ulp_mapper_tbl_info *tbl)
2232 {
2233 	struct bnxt_ulp_mapper_key_info	*kflds;
2234 	struct ulp_blob key, data;
2235 	uint32_t i, num_kflds;
2236 	uint16_t tmplen;
2237 	struct tf *tfp;
2238 	struct ulp_flow_db_res_params	fid_parms = { 0 };
2239 	struct tf_insert_em_entry_parms iparms = { 0 };
2240 	struct tf_delete_em_entry_parms free_parms = { 0 };
2241 	enum bnxt_ulp_flow_mem_type mtype;
2242 	struct bnxt_ulp_device_params *dparms = parms->device_params;
2243 	int32_t	trc;
2244 	int32_t rc = 0;
2245 	int32_t pad = 0;
2246 	enum bnxt_ulp_byte_order key_order, res_order;
2247 
2248 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2249 	rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2250 	if (rc) {
2251 		BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2252 		return -EINVAL;
2253 	}
2254 
2255 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2256 	if (!kflds || !num_kflds) {
2257 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2258 		return -EINVAL;
2259 	}
2260 
2261 	key_order = dparms->em_byte_order;
2262 	res_order = dparms->em_byte_order;
2263 
2264 	/* Initialize the key/result blobs */
2265 	if (!ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) ||
2266 	    !ulp_blob_init(&data, tbl->result_bit_size, res_order)) {
2267 		BNXT_TF_DBG(ERR, "blob inits failed.\n");
2268 		return -EINVAL;
2269 	}
2270 
2271 	/* create the key */
2272 	for (i = 0; i < num_kflds; i++) {
2273 		/* Setup the key */
2274 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2275 						  &kflds[i].field_info_spec,
2276 						  &key, 1, "EM Key");
2277 		if (rc) {
2278 			BNXT_TF_DBG(ERR, "Key field set failed.\n");
2279 			return rc;
2280 		}
2281 	}
2282 
2283 	/* if dynamic padding is enabled then add padding to result data */
2284 	if (dparms->dynamic_pad_en) {
2285 		/* add padding to make sure key is at byte boundary */
2286 		ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2287 
2288 		/* add the pad */
2289 		pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2290 		if (pad < 0) {
2291 			BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2292 			return -EINVAL;
2293 		}
2294 		ulp_blob_pad_push(&data, (uint32_t)pad);
2295 	}
2296 
2297 	/* Create the result data blob */
2298 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2299 	if (rc) {
2300 		BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2301 		return rc;
2302 	}
2303 	if (dparms->dynamic_pad_en) {
2304 		uint32_t abits = dparms->em_blk_align_bits;
2305 
2306 		/* when dynamic padding is enabled merge result + key */
2307 		rc = ulp_blob_block_merge(&data, &key, abits, pad);
2308 		if (rc) {
2309 			BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2310 			return rc;
2311 		}
2312 
2313 		/* add padding to make sure merged result is at slice boundary*/
2314 		ulp_blob_pad_align(&data, abits);
2315 
2316 		ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2317 	}
2318 
2319 	/* do the transpose for the internal EM keys */
2320 	if (tbl->resource_type == TF_MEM_INTERNAL) {
2321 		if (dparms->em_key_align_bytes) {
2322 			int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2323 
2324 			tmplen = ulp_blob_data_len_get(&key);
2325 			ulp_blob_pad_push(&key, b - tmplen);
2326 		}
2327 		tmplen = ulp_blob_data_len_get(&key);
2328 		ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2329 	}
2330 
2331 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2332 					     &iparms.tbl_scope_id);
2333 	if (rc) {
2334 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2335 		return rc;
2336 	}
2337 
2338 	/*
2339 	 * NOTE: the actual blob size will differ from the size in the tbl
2340 	 * entry due to the padding.
2341 	 */
2342 	iparms.dup_check		= 0;
2343 	iparms.dir			= tbl->direction;
2344 	iparms.mem			= tbl->resource_type;
2345 	iparms.key			= ulp_blob_data_get(&key, &tmplen);
2346 	iparms.key_sz_in_bits		= tbl->key_bit_size;
2347 	iparms.em_record		= ulp_blob_data_get(&data, &tmplen);
2348 	if (tbl->result_bit_size)
2349 		iparms.em_record_sz_in_bits	= tbl->result_bit_size;
2350 	else
2351 		iparms.em_record_sz_in_bits	= tmplen;
2352 
2353 	rc = tf_insert_em_entry(tfp, &iparms);
2354 	if (rc) {
2355 		BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2356 		return rc;
2357 	}
2358 
2359 	/* Mark action process */
2360 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2361 	    tbl->resource_type == TF_MEM_EXTERNAL)
2362 		rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2363 	else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2364 		 tbl->resource_type == TF_MEM_INTERNAL)
2365 		rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2366 	if (rc) {
2367 		BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2368 		goto error;
2369 	}
2370 
2371 	/* Link the EM resource to the flow in the flow db */
2372 	memset(&fid_parms, 0, sizeof(fid_parms));
2373 	fid_parms.direction		= tbl->direction;
2374 	fid_parms.resource_func		= tbl->resource_func;
2375 	fid_parms.resource_type		= tbl->resource_type;
2376 	fid_parms.critical_resource	= tbl->critical_resource;
2377 	fid_parms.resource_hndl		= iparms.flow_handle;
2378 
2379 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2380 	if (rc) {
2381 		BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2382 			    rc);
2383 		/* Need to free the identifier, so goto error */
2384 		goto error;
2385 	}
2386 
2387 	return 0;
2388 error:
2389 	free_parms.dir		= iparms.dir;
2390 	free_parms.mem		= iparms.mem;
2391 	free_parms.tbl_scope_id	= iparms.tbl_scope_id;
2392 	free_parms.flow_handle	= iparms.flow_handle;
2393 
2394 	trc = tf_delete_em_entry(tfp, &free_parms);
2395 	if (trc)
2396 		BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2397 
2398 	return rc;
2399 }
2400 
2401 static int32_t
ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)2402 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2403 			     struct bnxt_ulp_mapper_tbl_info *tbl)
2404 {
2405 	struct ulp_flow_db_res_params fid_parms;
2406 	struct ulp_blob	data;
2407 	uint64_t regval = 0;
2408 	uint16_t tmplen;
2409 	uint32_t index;
2410 	int32_t rc = 0, trc = 0;
2411 	struct tf_alloc_tbl_entry_parms aparms = { 0 };
2412 	struct tf_set_tbl_entry_parms sparms = { 0 };
2413 	struct tf_get_tbl_entry_parms gparms = { 0 };
2414 	struct tf_free_tbl_entry_parms free_parms = { 0 };
2415 	uint32_t tbl_scope_id;
2416 	struct tf *tfp;
2417 	struct bnxt_ulp_glb_resource_info glb_res = { 0 };
2418 	uint16_t bit_size;
2419 	bool alloc = false;
2420 	bool write = false;
2421 	bool global = false;
2422 	uint64_t act_rec_size;
2423 	bool shared = false;
2424 	enum tf_tbl_type tbl_type = tbl->resource_type;
2425 
2426 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2427 	/* compute the blob size */
2428 	bit_size = ulp_mapper_dyn_blob_size_get(parms, tbl);
2429 
2430 	/* Initialize the blob data */
2431 	if (!ulp_blob_init(&data, bit_size,
2432 			   parms->device_params->result_byte_order)) {
2433 		BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2434 		return -EINVAL;
2435 	}
2436 
2437 	/* Get the scope id first */
2438 	rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2439 	if (rc) {
2440 		BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2441 		return rc;
2442 	}
2443 
2444 	switch (tbl->tbl_opcode) {
2445 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2446 		alloc = true;
2447 		break;
2448 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2449 		/*
2450 		 * Build the entry, alloc an index, write the table, and store
2451 		 * the data in the regfile.
2452 		 */
2453 		alloc = true;
2454 		write = true;
2455 		break;
2456 	case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2457 		/*
2458 		 * get the index to write to from the regfile and then write
2459 		 * the table entry.
2460 		 */
2461 		if (!ulp_regfile_read(parms->regfile,
2462 				      tbl->tbl_operand,
2463 				      &regval)) {
2464 			BNXT_TF_DBG(ERR,
2465 				    "Failed to get tbl idx from regfile[%d].\n",
2466 				    tbl->tbl_operand);
2467 			return -EINVAL;
2468 		}
2469 		index = tfp_be_to_cpu_64(regval);
2470 		/* For external, we need to reverse shift */
2471 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2472 			index = TF_ACT_REC_PTR_2_OFFSET(index);
2473 
2474 		write = true;
2475 		break;
2476 	case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2477 		/*
2478 		 * Build the entry, alloc an index, write the table, and store
2479 		 * the data in the global regfile.
2480 		 */
2481 		alloc = true;
2482 		global = true;
2483 		write = true;
2484 		glb_res.direction = tbl->direction;
2485 		glb_res.resource_func = tbl->resource_func;
2486 		glb_res.resource_type = tbl->resource_type;
2487 		glb_res.glb_regfile_index = tbl->tbl_operand;
2488 		break;
2489 	case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2490 		if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2491 			BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2492 			return -EINVAL;
2493 		}
2494 		/*
2495 		 * get the index to write to from the global regfile and then
2496 		 * write the table.
2497 		 */
2498 		if (ulp_mapper_glb_resource_read(parms->mapper_data,
2499 						 tbl->direction,
2500 						 tbl->tbl_operand,
2501 						 &regval, &shared)) {
2502 			BNXT_TF_DBG(ERR,
2503 				    "Failed to get tbl idx from Glb RF[%d].\n",
2504 				    tbl->tbl_operand);
2505 			return -EINVAL;
2506 		}
2507 		index = tfp_be_to_cpu_64(regval);
2508 		/* For external, we need to reverse shift */
2509 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2510 			index = TF_ACT_REC_PTR_2_OFFSET(index);
2511 		write = true;
2512 		break;
2513 	case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2514 		/*
2515 		 * The read is different from the rest and can be handled here
2516 		 * instead of trying to use common code.  Simply read the table
2517 		 * with the index from the regfile, scan and store the
2518 		 * identifiers, and return.
2519 		 */
2520 		if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2521 			/* Not currently supporting with EXT */
2522 			BNXT_TF_DBG(ERR,
2523 				    "Ext Table Read Opcode not supported.\n");
2524 			return -EINVAL;
2525 		}
2526 		if (!ulp_regfile_read(parms->regfile,
2527 				      tbl->tbl_operand, &regval)) {
2528 			BNXT_TF_DBG(ERR,
2529 				    "Failed to get tbl idx from regfile[%d]\n",
2530 				    tbl->tbl_operand);
2531 			return -EINVAL;
2532 		}
2533 		index = tfp_be_to_cpu_64(regval);
2534 		gparms.dir = tbl->direction;
2535 		gparms.type = tbl->resource_type;
2536 		gparms.data = ulp_blob_data_get(&data, &tmplen);
2537 		gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2538 		gparms.idx = index;
2539 		rc = tf_get_tbl_entry(tfp, &gparms);
2540 		if (rc) {
2541 			BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2542 				    tbl->resource_type, index);
2543 			return rc;
2544 		}
2545 		/*
2546 		 * Scan the fields in the entry and push them into the regfile.
2547 		 */
2548 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2549 						   gparms.data,
2550 						   gparms.data_sz_in_bytes,
2551 						   data.byte_order);
2552 		if (rc) {
2553 			BNXT_TF_DBG(ERR,
2554 				    "Failed to get flds on tbl read rc=%d\n",
2555 				    rc);
2556 			return rc;
2557 		}
2558 		return 0;
2559 	default:
2560 		BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2561 			    tbl->tbl_opcode);
2562 		return -EINVAL;
2563 	}
2564 
2565 	if (write) {
2566 		/* Get the result fields list */
2567 		rc = ulp_mapper_tbl_result_build(parms,
2568 						 tbl,
2569 						 &data,
2570 						 "Indexed Result");
2571 		if (rc) {
2572 			BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2573 			return rc;
2574 		}
2575 	}
2576 
2577 	if (alloc) {
2578 		aparms.dir		= tbl->direction;
2579 		tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl,
2580 						       &data, &tmplen);
2581 		aparms.type = tbl_type;
2582 		aparms.tbl_scope_id	= tbl_scope_id;
2583 
2584 		/* All failures after the alloc succeeds require a free */
2585 		rc = tf_alloc_tbl_entry(tfp, &aparms);
2586 		if (rc) {
2587 			BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2588 				    tf_tbl_type_2_str(aparms.type),
2589 				    tf_dir_2_str(tbl->direction), rc);
2590 			return rc;
2591 		}
2592 		index = aparms.idx;
2593 
2594 		/*
2595 		 * Store the index in the regfile since we either allocated it
2596 		 * or it was a hit.
2597 		 *
2598 		 * Calculate the idx for the result record, for external EM the
2599 		 * offset needs to be shifted accordingly.
2600 		 * If external non-inline table types are used then need to
2601 		 * revisit this logic.
2602 		 */
2603 		if (tbl->resource_type == TF_TBL_TYPE_EXT)
2604 			regval = TF_ACT_REC_OFFSET_2_PTR(index);
2605 		else
2606 			regval = index;
2607 		regval = tfp_cpu_to_be_64(regval);
2608 
2609 		if (global) {
2610 			/*
2611 			 * Shared resources are never allocated through this
2612 			 * method, so the shared flag is always false.
2613 			 */
2614 			rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2615 							   &glb_res, regval,
2616 							   false);
2617 		} else {
2618 			rc = ulp_regfile_write(parms->regfile,
2619 					       tbl->tbl_operand, regval);
2620 		}
2621 		if (rc) {
2622 			BNXT_TF_DBG(ERR,
2623 				    "Failed to write %s regfile[%d] rc=%d\n",
2624 				    (global) ? "global" : "reg",
2625 				    tbl->tbl_operand, rc);
2626 			goto error;
2627 		}
2628 	}
2629 
2630 	if (write) {
2631 		sparms.dir = tbl->direction;
2632 		sparms.data = ulp_blob_data_get(&data, &tmplen);
2633 		tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, &data,
2634 						       &tmplen);
2635 		sparms.type = tbl_type;
2636 		sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2637 		sparms.idx = index;
2638 		sparms.tbl_scope_id = tbl_scope_id;
2639 		if (shared)
2640 			tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx);
2641 		rc = tf_set_tbl_entry(tfp, &sparms);
2642 		if (rc) {
2643 			BNXT_TF_DBG(ERR,
2644 				    "Index table[%s][%s][%x] write fail rc=%d\n",
2645 				    tf_tbl_type_2_str(sparms.type),
2646 				    tf_dir_2_str(sparms.dir),
2647 				    sparms.idx, rc);
2648 			goto error;
2649 		}
2650 		BNXT_TF_INF("Index table[%s][%s][%x] write successful.\n",
2651 			    tf_tbl_type_2_str(sparms.type),
2652 			    tf_dir_2_str(sparms.dir), sparms.idx);
2653 
2654 		/* Calculate action record size */
2655 		if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2656 			act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2657 			act_rec_size--;
2658 			if (ulp_regfile_write(parms->regfile,
2659 					      BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2660 					      tfp_cpu_to_be_64(act_rec_size)))
2661 				BNXT_TF_DBG(ERR,
2662 					    "Failed write the act rec size\n");
2663 		}
2664 	}
2665 
2666 	/* Link the resource to the flow in the flow db */
2667 	memset(&fid_parms, 0, sizeof(fid_parms));
2668 	fid_parms.direction	= tbl->direction;
2669 	fid_parms.resource_func	= tbl->resource_func;
2670 	fid_parms.resource_type	= tbl_type;
2671 	fid_parms.resource_sub_type = tbl->resource_sub_type;
2672 	fid_parms.resource_hndl	= index;
2673 	fid_parms.critical_resource = tbl->critical_resource;
2674 	ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2675 
2676 	rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2677 	if (rc) {
2678 		BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2679 			    rc);
2680 		goto error;
2681 	}
2682 
2683 	/* Perform the VF rep action */
2684 	rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2685 	if (rc) {
2686 		BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2687 		goto error;
2688 	}
2689 	return rc;
2690 error:
2691 	/* Shared resources are not freed */
2692 	if (shared)
2693 		return rc;
2694 	/*
2695 	 * Free the allocated resource since we failed to either
2696 	 * write to the entry or link the flow
2697 	 */
2698 	free_parms.dir	= tbl->direction;
2699 	free_parms.type	= tbl_type;
2700 	free_parms.idx	= index;
2701 	free_parms.tbl_scope_id = tbl_scope_id;
2702 
2703 	trc = tf_free_tbl_entry(tfp, &free_parms);
2704 	if (trc)
2705 		BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2706 
2707 	return rc;
2708 }
2709 
2710 static int32_t
ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)2711 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2712 			  struct bnxt_ulp_mapper_tbl_info *tbl)
2713 {
2714 	struct ulp_blob	data, res_blob;
2715 	uint64_t idx;
2716 	uint16_t tmplen;
2717 	int32_t rc = 0;
2718 	struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2719 	struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2720 	struct tf *tfp;
2721 	enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2722 	uint32_t res_size;
2723 
2724 	tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2725 	/* Initialize the blob data */
2726 	if (!ulp_blob_init(&data, tbl->result_bit_size,
2727 			   parms->device_params->result_byte_order)) {
2728 		BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2729 		return -EINVAL;
2730 	}
2731 
2732 	/* create the result blob */
2733 	rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2734 	if (rc) {
2735 		BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2736 		return rc;
2737 	}
2738 
2739 	/* Get the index details */
2740 	switch (if_opc) {
2741 	case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2742 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2743 		break;
2744 	case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2745 		if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2746 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2747 				    tbl->tbl_operand);
2748 			return -EINVAL;
2749 		}
2750 		idx = tfp_be_to_cpu_64(idx);
2751 		break;
2752 	case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2753 		idx = tbl->tbl_operand;
2754 		break;
2755 	case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2756 		/* Initialize the result blob */
2757 		if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2758 				   parms->device_params->result_byte_order)) {
2759 			BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2760 			return -EINVAL;
2761 		}
2762 
2763 		/* read the interface table */
2764 		idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2765 		res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2766 		get_parms.dir = tbl->direction;
2767 		get_parms.type = tbl->resource_type;
2768 		get_parms.idx = idx;
2769 		get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2770 		get_parms.data_sz_in_bytes = res_size;
2771 
2772 		rc = tf_get_if_tbl_entry(tfp, &get_parms);
2773 		if (rc) {
2774 			BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2775 				    get_parms.type,
2776 				    tf_dir_2_str(get_parms.dir),
2777 				    get_parms.idx, rc);
2778 			return rc;
2779 		}
2780 		rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2781 						   res_blob.data,
2782 						   res_size,
2783 						   res_blob.byte_order);
2784 		if (rc)
2785 			BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2786 		return rc;
2787 	case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2788 		return rc; /* skip it */
2789 	default:
2790 		BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2791 		return -EINVAL;
2792 	}
2793 
2794 	/* Perform the tf table set by filling the set params */
2795 	iftbl_params.dir = tbl->direction;
2796 	iftbl_params.type = tbl->resource_type;
2797 	iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2798 	iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2799 	iftbl_params.idx = idx;
2800 
2801 	rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2802 	if (rc) {
2803 		BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2804 			    iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2805 			    tf_dir_2_str(iftbl_params.dir),
2806 			    iftbl_params.idx, rc);
2807 		return rc;
2808 	}
2809 	BNXT_TF_INF("Set table[%s][%s][%x] success.\n",
2810 		    tf_if_tbl_2_str(iftbl_params.type),
2811 		    tf_dir_2_str(iftbl_params.dir),
2812 		    iftbl_params.idx);
2813 
2814 	/*
2815 	 * TBD: Need to look at the need to store idx in flow db for restore
2816 	 * the table to its original state on deletion of this entry.
2817 	 */
2818 	return rc;
2819 }
2820 
2821 static int32_t
ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)2822 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2823 			   struct bnxt_ulp_mapper_tbl_info *tbl)
2824 {
2825 	struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2826 	struct bnxt_ulp_mapper_key_info *kflds;
2827 	struct ulp_flow_db_res_params fid_parms;
2828 	struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2829 	struct ulp_gen_hash_entry_params hash_entry;
2830 	uint16_t tmplen = 0;
2831 	struct ulp_blob key, data;
2832 	uint8_t *cache_key;
2833 	int32_t tbl_idx;
2834 	uint32_t i, num_kflds = 0, key_index = 0;
2835 	uint32_t gen_tbl_miss = 1, fdb_write = 0;
2836 	uint8_t *byte_data;
2837 	int32_t rc = 0;
2838 
2839 	/* Get the key fields list and build the key. */
2840 	kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2841 	if (!kflds || !num_kflds) {
2842 		BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2843 		return -EINVAL;
2844 	}
2845 
2846 	if (!ulp_blob_init(&key, tbl->key_bit_size,
2847 			   parms->device_params->key_byte_order)) {
2848 		BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2849 		return -EINVAL;
2850 	}
2851 	for (i = 0; i < num_kflds; i++) {
2852 		/* Setup the key */
2853 		rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2854 						  &kflds[i].field_info_spec,
2855 						  &key, 1, "Gen Tbl Key");
2856 		if (rc) {
2857 			BNXT_TF_DBG(ERR,
2858 				    "Failed to create key for Gen tbl rc=%d\n",
2859 				    rc);
2860 			return -EINVAL;
2861 		}
2862 	}
2863 
2864 	/* Calculate the table index for the generic table*/
2865 	tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2866 						   tbl->direction);
2867 	if (tbl_idx < 0) {
2868 		BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2869 			    tbl->resource_sub_type, tbl->direction);
2870 		return -EINVAL;
2871 	}
2872 
2873 	/* The_key is a byte array convert it to a search index */
2874 	cache_key = ulp_blob_data_get(&key, &tmplen);
2875 	/* get the generic table  */
2876 	gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2877 
2878 	/* Check if generic hash table */
2879 	if (gen_tbl_list->hash_tbl) {
2880 		if (tbl->gen_tbl_lkup_type !=
2881 		    BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2882 			BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2883 				    gen_tbl_list->gen_tbl_name);
2884 			return -EINVAL;
2885 		}
2886 		hash_entry.key_data = cache_key;
2887 		hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2888 		rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2889 						      &hash_entry);
2890 		if (rc) {
2891 			BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2892 				    gen_tbl_list->gen_tbl_name);
2893 			return rc;
2894 		}
2895 		if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2896 			key_index = hash_entry.key_idx;
2897 			/* Get the generic table entry */
2898 			if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2899 							 key_index,
2900 							 &gen_tbl_ent))
2901 				return -EINVAL;
2902 			/* store the hash index in the fdb */
2903 			key_index = hash_entry.hash_index;
2904 		}
2905 	} else {
2906 		/* convert key to index directly */
2907 		if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) {
2908 			BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n",
2909 				    gen_tbl_list->gen_tbl_name);
2910 			return -EINVAL;
2911 		}
2912 		memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2913 		/* Get the generic table entry */
2914 		if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2915 						 &gen_tbl_ent))
2916 			return -EINVAL;
2917 	}
2918 	switch (tbl->tbl_opcode) {
2919 	case BNXT_ULP_GENERIC_TBL_OPC_READ:
2920 		if (gen_tbl_list->hash_tbl) {
2921 			if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
2922 				break; /* nothing to be done , no entry */
2923 		}
2924 
2925 		/* check the reference count */
2926 		if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2927 			g = &gen_tbl_ent;
2928 			/* Scan ident list and create the result blob*/
2929 			rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2930 							   g->byte_data,
2931 							   g->byte_data_size,
2932 							   g->byte_order);
2933 			if (rc) {
2934 				BNXT_TF_DBG(ERR,
2935 					    "Failed to scan ident list\n");
2936 				return -EINVAL;
2937 			}
2938 			if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2939 				/* increment the reference count */
2940 				ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2941 			}
2942 
2943 			/* it is a hit */
2944 			gen_tbl_miss = 0;
2945 			fdb_write = 1;
2946 		}
2947 		break;
2948 	case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2949 		if (gen_tbl_list->hash_tbl) {
2950 			rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
2951 							       &hash_entry,
2952 							       &gen_tbl_ent);
2953 			if (rc)
2954 				return rc;
2955 			/* store the hash index in the fdb */
2956 			key_index = hash_entry.hash_index;
2957 		}
2958 		/* check the reference count */
2959 		if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2960 			/* a hit then error */
2961 			BNXT_TF_DBG(ERR, "generic entry already present\n");
2962 			return -EINVAL; /* success */
2963 		}
2964 
2965 		/* Initialize the blob data */
2966 		if (!ulp_blob_init(&data, tbl->result_bit_size,
2967 				   gen_tbl_ent.byte_order)) {
2968 			BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2969 			return -EINVAL;
2970 		}
2971 
2972 		/* Get the result fields list */
2973 		rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2974 						 "Gen tbl Result");
2975 		if (rc) {
2976 			BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2977 			return rc;
2978 		}
2979 		byte_data = ulp_blob_data_get(&data, &tmplen);
2980 		rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2981 						       tmplen, byte_data,
2982 						       ULP_BITS_2_BYTE(tmplen));
2983 		if (rc) {
2984 			BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2985 			return -EINVAL;
2986 		}
2987 
2988 		/* increment the reference count */
2989 		ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2990 		fdb_write = 1;
2991 		parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
2992 		break;
2993 	default:
2994 		BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2995 		return -EINVAL;
2996 	}
2997 
2998 	/* Set the generic entry hit */
2999 	rc = ulp_regfile_write(parms->regfile,
3000 			       BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3001 			       tfp_cpu_to_be_64(gen_tbl_miss));
3002 	if (rc) {
3003 		BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
3004 			    BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3005 		return -EIO;
3006 	}
3007 
3008 	/* add the entry to the flow database */
3009 	if (fdb_write) {
3010 		memset(&fid_parms, 0, sizeof(fid_parms));
3011 		fid_parms.direction = tbl->direction;
3012 		fid_parms.resource_func	= tbl->resource_func;
3013 		fid_parms.resource_sub_type = tbl->resource_sub_type;
3014 		fid_parms.resource_hndl	= key_index;
3015 		fid_parms.critical_resource = tbl->critical_resource;
3016 		ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
3017 
3018 		rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
3019 		if (rc)
3020 			BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
3021 	}
3022 	return rc;
3023 }
3024 
3025 static int32_t
ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)3026 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
3027 			    struct bnxt_ulp_mapper_tbl_info *tbl)
3028 {
3029 	int32_t rc = 0;
3030 
3031 	/* process the fdb opcode for alloc push */
3032 	if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
3033 		rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
3034 		if (rc) {
3035 			BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
3036 			return rc;
3037 		}
3038 	}
3039 	return rc;
3040 }
3041 
3042 static int32_t
ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_data * mapper_data)3043 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3044 				  struct bnxt_ulp_mapper_data *mapper_data)
3045 {
3046 	struct bnxt_ulp_glb_resource_info *glb_res;
3047 	uint32_t num_glb_res_ids, idx, dev_id;
3048 	uint8_t app_id;
3049 	int32_t rc = 0;
3050 
3051 	glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
3052 	if (!glb_res || !num_glb_res_ids) {
3053 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3054 		return -EINVAL;
3055 	}
3056 
3057 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3058 	if (rc) {
3059 		BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
3060 			    rc);
3061 		return rc;
3062 	}
3063 
3064 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3065 	if (rc) {
3066 		BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
3067 			    rc);
3068 		return rc;
3069 	}
3070 
3071 	/* Iterate the global resources and process each one */
3072 	for (idx = 0; idx < num_glb_res_ids; idx++) {
3073 		if (dev_id != glb_res[idx].device_id ||
3074 		    glb_res[idx].app_id != app_id)
3075 			continue;
3076 		switch (glb_res[idx].resource_func) {
3077 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3078 			rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
3079 								mapper_data,
3080 								&glb_res[idx]);
3081 			break;
3082 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3083 			rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
3084 								 mapper_data,
3085 								 &glb_res[idx]);
3086 			break;
3087 		default:
3088 			BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
3089 				    glb_res[idx].resource_func);
3090 			rc = -EINVAL;
3091 			break;
3092 		}
3093 		if (rc)
3094 			return rc;
3095 	}
3096 	return rc;
3097 }
3098 
3099 /*
3100  * Iterate over the shared resources assigned during tf_open_session and store
3101  * them in the global regfile with the shared flag.
3102  */
3103 static int32_t
ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_data * mapper_data)3104 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
3105 				      struct bnxt_ulp_mapper_data *mapper_data)
3106 {
3107 	struct tf_get_shared_tbl_increment_parms iparms;
3108 	struct bnxt_ulp_glb_resource_info *glb_res;
3109 	struct tf_get_session_info_parms sparms;
3110 	uint32_t num_entries, i, dev_id, res;
3111 	struct tf_resource_info *res_info;
3112 	uint32_t addend;
3113 	uint64_t regval;
3114 	enum tf_dir dir;
3115 	int32_t rc = 0;
3116 	struct tf *tfp;
3117 	uint8_t app_id;
3118 
3119 	memset(&sparms, 0, sizeof(sparms));
3120 	glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries);
3121 	if (!glb_res || !num_entries) {
3122 		BNXT_TF_DBG(ERR, "Invalid Arguments\n");
3123 		return -EINVAL;
3124 	}
3125 	tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx);
3126 	if (!tfp) {
3127 		BNXT_TF_DBG(ERR, "Failed to get tfp for app global init");
3128 		return -EINVAL;
3129 	}
3130 	/*
3131 	 * Retrieve the resources that were assigned during the shared session
3132 	 * creation.
3133 	 */
3134 	rc = tf_get_session_info(tfp, &sparms);
3135 	if (rc) {
3136 		BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc);
3137 		return rc;
3138 	}
3139 
3140 	rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
3141 	if (rc) {
3142 		BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n",
3143 			    rc);
3144 		return rc;
3145 	}
3146 
3147 	rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
3148 	if (rc) {
3149 		BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n",
3150 			    rc);
3151 		return rc;
3152 	}
3153 
3154 	/* Store all the app global resources */
3155 	for (i = 0; i < num_entries; i++) {
3156 		if (dev_id != glb_res[i].device_id ||
3157 		    app_id != glb_res[i].app_id)
3158 			continue;
3159 		dir = glb_res[i].direction;
3160 		res = glb_res[i].resource_type;
3161 		addend = 1;
3162 
3163 		switch (glb_res[i].resource_func) {
3164 		case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3165 			res_info = &sparms.session_info.ident[dir].info[res];
3166 			break;
3167 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3168 			/*
3169 			 * Tables may have various strides for the allocations.
3170 			 * Need to account.
3171 			 */
3172 			memset(&iparms, 0, sizeof(iparms));
3173 			iparms.dir = dir;
3174 			iparms.type = res;
3175 			rc = tf_get_shared_tbl_increment(tfp, &iparms);
3176 			if (rc) {
3177 				BNXT_TF_DBG(ERR,
3178 					    "Failed to get addend for %s[%s] rc=(%d)\n",
3179 					    tf_tbl_type_2_str(res),
3180 					    tf_dir_2_str(dir), rc);
3181 				return rc;
3182 			}
3183 			addend = iparms.increment_cnt;
3184 			res_info = &sparms.session_info.tbl[dir].info[res];
3185 			break;
3186 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3187 			res_info = &sparms.session_info.tcam[dir].info[res];
3188 			break;
3189 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3190 			res_info = &sparms.session_info.em[dir].info[res];
3191 			break;
3192 		default:
3193 			BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n",
3194 				    glb_res[i].resource_func);
3195 			continue;
3196 		}
3197 		regval = tfp_cpu_to_be_64((uint64_t)res_info->start);
3198 		res_info->start += addend;
3199 		/*
3200 		 * All resources written to the global regfile are shared for
3201 		 * this function.
3202 		 */
3203 		rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i],
3204 						   regval, true);
3205 		if (rc)
3206 			return rc;
3207 	}
3208 
3209 	return rc;
3210 }
3211 
3212 /*
3213  * Common conditional opcode process routine that is used for both the template
3214  * rejection and table conditional execution.
3215  */
3216 static int32_t
ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms * parms,enum bnxt_ulp_cond_opc opc,uint32_t operand,int32_t * res)3217 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
3218 			    enum bnxt_ulp_cond_opc opc,
3219 			    uint32_t operand,
3220 			    int32_t *res)
3221 {
3222 	enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
3223 	int32_t rc = 0;
3224 	uint8_t bit;
3225 	uint64_t regval;
3226 
3227 	switch (opc) {
3228 	case BNXT_ULP_COND_OPC_CF_IS_SET:
3229 		if (operand < BNXT_ULP_CF_IDX_LAST) {
3230 			*res = ULP_COMP_FLD_IDX_RD(parms, operand);
3231 		} else {
3232 			BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3233 				    operand);
3234 			rc = -EINVAL;
3235 		}
3236 		break;
3237 	case BNXT_ULP_COND_OPC_CF_NOT_SET:
3238 		if (operand < BNXT_ULP_CF_IDX_LAST) {
3239 			*res = !ULP_COMP_FLD_IDX_RD(parms, operand);
3240 		} else {
3241 			BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3242 				    operand);
3243 			rc = -EINVAL;
3244 		}
3245 		break;
3246 	case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
3247 		if (operand < BNXT_ULP_ACT_BIT_LAST) {
3248 			*res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3249 						operand);
3250 		} else {
3251 			BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3252 				    operand);
3253 			rc = -EINVAL;
3254 		}
3255 		break;
3256 	case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
3257 		if (operand < BNXT_ULP_ACT_BIT_LAST) {
3258 			*res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3259 					       operand);
3260 		} else {
3261 			BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3262 				    operand);
3263 			rc = -EINVAL;
3264 		}
3265 		break;
3266 	case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
3267 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3268 			*res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3269 						operand);
3270 		} else {
3271 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3272 				    operand);
3273 			rc = -EINVAL;
3274 		}
3275 		break;
3276 	case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
3277 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3278 			*res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3279 					       operand);
3280 		} else {
3281 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3282 				    operand);
3283 			rc = -EINVAL;
3284 		}
3285 		break;
3286 	case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
3287 		rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3288 		if (rc) {
3289 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3290 				    operand);
3291 			return -EINVAL;
3292 		}
3293 		*res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3294 		break;
3295 	case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
3296 		rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3297 		if (rc) {
3298 			BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3299 				    operand);
3300 			return -EINVAL;
3301 		}
3302 		*res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3303 		break;
3304 	case BNXT_ULP_COND_OPC_RF_IS_SET:
3305 		if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3306 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3307 			return -EINVAL;
3308 		}
3309 		*res = regval != 0;
3310 		break;
3311 	case BNXT_ULP_COND_OPC_RF_NOT_SET:
3312 		if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3313 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3314 			return -EINVAL;
3315 		}
3316 		*res = regval == 0;
3317 		break;
3318 	case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
3319 		*res = parms->flow_pattern_id == operand;
3320 		break;
3321 	case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
3322 		*res = parms->act_pattern_id == operand;
3323 		break;
3324 	case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
3325 		if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3326 			BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3327 			return -EINVAL;
3328 		}
3329 		*res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
3330 		break;
3331 	case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
3332 		if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3333 			BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3334 			return -EINVAL;
3335 		}
3336 		*res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
3337 		break;
3338 	case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET:
3339 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3340 			*res = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3341 						operand);
3342 		} else {
3343 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3344 				    operand);
3345 			rc = -EINVAL;
3346 		}
3347 		break;
3348 	case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET:
3349 		if (operand < BNXT_ULP_HDR_BIT_LAST) {
3350 			*res = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits,
3351 						 operand);
3352 		} else {
3353 			BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3354 				    operand);
3355 			rc = -EINVAL;
3356 		}
3357 		break;
3358 	default:
3359 		BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
3360 		rc = -EINVAL;
3361 		break;
3362 	}
3363 	return (rc);
3364 }
3365 
3366 static int32_t
ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms * parms,enum tf_dir dir,enum bnxt_ulp_func_src func_src,uint16_t func_opr,uint64_t * result)3367 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms,
3368 			    enum tf_dir dir,
3369 			    enum bnxt_ulp_func_src func_src,
3370 			    uint16_t func_opr,
3371 			    uint64_t *result)
3372 {
3373 	uint64_t regval;
3374 	bool shared;
3375 
3376 	*result =  false;
3377 	switch (func_src) {
3378 	case BNXT_ULP_FUNC_SRC_COMP_FIELD:
3379 		if (func_opr >= BNXT_ULP_CF_IDX_LAST) {
3380 			BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr);
3381 			return -EINVAL;
3382 		}
3383 		*result = ULP_COMP_FLD_IDX_RD(parms, func_opr);
3384 		break;
3385 	case BNXT_ULP_FUNC_SRC_REGFILE:
3386 		if (!ulp_regfile_read(parms->regfile, func_opr, &regval)) {
3387 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr);
3388 			return -EINVAL;
3389 		}
3390 		*result = tfp_be_to_cpu_64(regval);
3391 		break;
3392 	case BNXT_ULP_FUNC_SRC_GLB_REGFILE:
3393 		if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3394 						 func_opr, &regval, &shared)) {
3395 			BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3396 				    func_opr);
3397 			return -EINVAL;
3398 		}
3399 		*result = tfp_be_to_cpu_64(regval);
3400 		break;
3401 	case BNXT_ULP_FUNC_SRC_CONST:
3402 		*result = func_opr;
3403 		break;
3404 	default:
3405 		BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src);
3406 		return -EINVAL;
3407 	}
3408 	return 0;
3409 }
3410 
3411 static int32_t
ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl)3412 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms,
3413 			     struct bnxt_ulp_mapper_tbl_info *tbl)
3414 {
3415 	struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info;
3416 	uint64_t res = 0, res1 = 0, res2 = 0;
3417 	int32_t rc = 0;
3418 	uint32_t process_src1 = 0, process_src2 = 0;
3419 
3420 	/* determine which functional operands to compute */
3421 	switch (func_info->func_opc) {
3422 	case BNXT_ULP_FUNC_OPC_NOP:
3423 		return rc;
3424 	case BNXT_ULP_FUNC_OPC_EQ:
3425 	case BNXT_ULP_FUNC_OPC_NE:
3426 	case BNXT_ULP_FUNC_OPC_GE:
3427 	case BNXT_ULP_FUNC_OPC_GT:
3428 	case BNXT_ULP_FUNC_OPC_LE:
3429 	case BNXT_ULP_FUNC_OPC_LT:
3430 		process_src1 = 1;
3431 		process_src2 = 1;
3432 		break;
3433 	case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3434 		process_src1 = 1;
3435 		break;
3436 	default:
3437 		break;
3438 	}
3439 
3440 	if (process_src1) {
3441 		rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3442 						 func_info->func_src1,
3443 						 func_info->func_opr1, &res1);
3444 		if (rc)
3445 			return rc;
3446 	}
3447 
3448 	if (process_src2) {
3449 		rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3450 						 func_info->func_src2,
3451 						 func_info->func_opr2, &res2);
3452 		if (rc)
3453 			return rc;
3454 	}
3455 
3456 	/* perform the functional opcode operations */
3457 	switch (func_info->func_opc) {
3458 	case BNXT_ULP_FUNC_OPC_EQ:
3459 		if (res1 == res2)
3460 			res = 1;
3461 		break;
3462 	case BNXT_ULP_FUNC_OPC_NE:
3463 		if (res1 != res2)
3464 			res = 1;
3465 		break;
3466 	case BNXT_ULP_FUNC_OPC_GE:
3467 		if (res1 >= res2)
3468 			res = 1;
3469 		break;
3470 	case BNXT_ULP_FUNC_OPC_GT:
3471 		if (res1 > res2)
3472 			res = 1;
3473 		break;
3474 	case BNXT_ULP_FUNC_OPC_LE:
3475 		if (res1 <= res2)
3476 			res = 1;
3477 		break;
3478 	case BNXT_ULP_FUNC_OPC_LT:
3479 		if (res1 < res2)
3480 			res = 1;
3481 		break;
3482 	case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3483 		res = res1;
3484 		break;
3485 	case BNXT_ULP_FUNC_OPC_RSS_CONFIG:
3486 		/* apply the rss config using pmd method */
3487 		return bnxt_rss_config_action_apply(parms);
3488 	case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR:
3489 		rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res);
3490 		if (rc)
3491 			return -EINVAL;
3492 		res = tfp_be_to_cpu_64(res);
3493 		break;
3494 	default:
3495 		BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc);
3496 		return -EINVAL;
3497 	}
3498 	if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr,
3499 			      tfp_cpu_to_be_64(res))) {
3500 		BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n",
3501 			    func_info->func_dst_opr);
3502 		return -EINVAL;
3503 	}
3504 
3505 	return rc;
3506 }
3507 
3508 /*
3509  * Processes a list of conditions and returns both a status and result of the
3510  * list.  The status must be checked prior to verifying the result.
3511  *
3512  * returns 0 for success, negative on failure
3513  * returns res = 1 for true, res = 0 for false.
3514  */
3515 static int32_t
ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms * parms,enum bnxt_ulp_cond_list_opc list_opc,struct bnxt_ulp_mapper_cond_info * list,uint32_t num,int32_t * res)3516 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3517 				 enum bnxt_ulp_cond_list_opc list_opc,
3518 				 struct bnxt_ulp_mapper_cond_info *list,
3519 				 uint32_t num,
3520 				 int32_t *res)
3521 {
3522 	uint32_t i;
3523 	int32_t rc = 0, trc = 0;
3524 
3525 	switch (list_opc) {
3526 	case BNXT_ULP_COND_LIST_OPC_AND:
3527 		/* AND Defaults to true. */
3528 		*res = 1;
3529 		break;
3530 	case BNXT_ULP_COND_LIST_OPC_OR:
3531 		/* OR Defaults to false. */
3532 		*res = 0;
3533 		break;
3534 	case BNXT_ULP_COND_LIST_OPC_TRUE:
3535 		*res = 1;
3536 		return rc;
3537 	case BNXT_ULP_COND_LIST_OPC_FALSE:
3538 		*res = 0;
3539 		return rc;
3540 	default:
3541 		BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3542 			    list_opc);
3543 		*res = 0;
3544 		return -EINVAL;
3545 	}
3546 
3547 	for (i = 0; i < num; i++) {
3548 		rc = ulp_mapper_cond_opc_process(parms,
3549 						 list[i].cond_opcode,
3550 						 list[i].cond_operand,
3551 						 &trc);
3552 		if (rc)
3553 			return rc;
3554 
3555 		if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3556 			/* early return if result is ever zero */
3557 			if (!trc) {
3558 				*res = trc;
3559 				return rc;
3560 			}
3561 		} else {
3562 			/* early return if result is ever non-zero */
3563 			if (trc) {
3564 				*res = trc;
3565 				return rc;
3566 			}
3567 		}
3568 	}
3569 
3570 	return rc;
3571 }
3572 
3573 /*
3574  * Processes conflict resolution and returns both a status and result.
3575  * The status must be checked prior to verifying the result.
3576  *
3577  * returns 0 for success, negative on failure
3578  * returns res = 1 for true, res = 0 for false.
3579  */
3580 static int32_t
ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms * parms,struct bnxt_ulp_mapper_tbl_info * tbl,int32_t * res)3581 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3582 				       struct bnxt_ulp_mapper_tbl_info *tbl,
3583 				       int32_t *res)
3584 {
3585 	int32_t rc = 0;
3586 	uint64_t regval;
3587 	uint64_t comp_sig;
3588 
3589 	*res = 0;
3590 	switch (tbl->accept_opcode) {
3591 	case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3592 		*res = 1;
3593 		break;
3594 	case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3595 		/* perform the signature validation*/
3596 		if (tbl->resource_func ==
3597 		    BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3598 			/* Perform the check that generic table is hit or not */
3599 			if (!ulp_regfile_read(parms->regfile,
3600 					      BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3601 					      &regval)) {
3602 				BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3603 					    BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3604 				return -EINVAL;
3605 			}
3606 			if (regval) {
3607 				/* not a hit so no need to check flow sign*/
3608 				*res = 1;
3609 				return rc;
3610 			}
3611 		}
3612 		/* compare the new flow signature against stored one */
3613 		if (!ulp_regfile_read(parms->regfile,
3614 				      BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3615 				      &regval)) {
3616 			BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3617 				    BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3618 			return -EINVAL;
3619 		}
3620 		comp_sig = ULP_COMP_FLD_IDX_RD(parms,
3621 					       BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3622 		regval = tfp_be_to_cpu_64(regval);
3623 		if (comp_sig == regval)
3624 			*res = 1;
3625 		else
3626 			BNXT_TF_DBG(ERR, "failed signature match 0x%016"
3627 				    PRIX64 ":%x\n", comp_sig, (uint32_t)regval);
3628 		break;
3629 	default:
3630 		BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3631 			    tbl->accept_opcode);
3632 		return -EINVAL;
3633 	}
3634 	return rc;
3635 }
3636 
3637 static int32_t
ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms * parms,uint32_t tid)3638 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3639 {
3640 	struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3641 	enum bnxt_ulp_cond_list_opc cond_opc;
3642 	struct bnxt_ulp_mapper_tbl_info *tbls;
3643 	struct bnxt_ulp_mapper_tbl_info *tbl;
3644 	uint32_t num_tbls, tbl_idx, num_cond_tbls;
3645 	int32_t rc = -EINVAL, cond_rc = 0;
3646 	int32_t cond_goto = 1;
3647 
3648 	cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3649 						    &num_cond_tbls,
3650 						    &cond_opc);
3651 	/*
3652 	 * Process the reject list if exists, otherwise assume that the
3653 	 * template is allowed.
3654 	 */
3655 	if (cond_tbls && num_cond_tbls) {
3656 		rc = ulp_mapper_cond_opc_list_process(parms,
3657 						      cond_opc,
3658 						      cond_tbls,
3659 						      num_cond_tbls,
3660 						      &cond_rc);
3661 		if (rc)
3662 			return rc;
3663 
3664 		/* Reject the template if True */
3665 		if (cond_rc) {
3666 			BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3667 				    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3668 				    tid);
3669 			return -EINVAL;
3670 		}
3671 	}
3672 
3673 	tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3674 	if (!tbls || !num_tbls) {
3675 		BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3676 			    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3677 			    parms->dev_id, tid);
3678 		return -EINVAL;
3679 	}
3680 
3681 	for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3682 		tbl = &tbls[tbl_idx];
3683 		cond_goto = tbl->execute_info.cond_true_goto;
3684 		/* Process the conditional func code opcodes */
3685 		if (ulp_mapper_func_info_process(parms, tbl)) {
3686 			BNXT_TF_DBG(ERR, "Failed to process cond update\n");
3687 			rc = -EINVAL;
3688 			goto error;
3689 		}
3690 
3691 		cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3692 							    &num_cond_tbls,
3693 							    &cond_opc);
3694 		rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3695 						      cond_tbls, num_cond_tbls,
3696 						      &cond_rc);
3697 		if (rc) {
3698 			BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n",
3699 				    rc);
3700 			goto error;
3701 		}
3702 		/* Skip the table if False */
3703 		if (!cond_rc) {
3704 			cond_goto = tbl->execute_info.cond_false_goto;
3705 			goto next_iteration;
3706 		}
3707 
3708 		switch (tbl->resource_func) {
3709 		case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3710 			rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3711 			break;
3712 		case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3713 			rc = ulp_mapper_em_tbl_process(parms, tbl);
3714 			break;
3715 		case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3716 			rc = ulp_mapper_index_tbl_process(parms, tbl);
3717 			break;
3718 		case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3719 			rc = ulp_mapper_if_tbl_process(parms, tbl);
3720 			break;
3721 		case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3722 			rc = ulp_mapper_gen_tbl_process(parms, tbl);
3723 			break;
3724 		case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3725 			rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3726 			break;
3727 		case BNXT_ULP_RESOURCE_FUNC_INVALID:
3728 			rc = 0;
3729 			break;
3730 		default:
3731 			BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3732 				    tbl->resource_func);
3733 			rc = -EINVAL;
3734 			goto error;
3735 		}
3736 
3737 		if (rc) {
3738 			BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3739 				    tbl->resource_func);
3740 			goto error;
3741 		}
3742 
3743 		/* perform the post table process */
3744 		rc  = ulp_mapper_conflict_resolution_process(parms, tbl,
3745 							     &cond_rc);
3746 		if (rc || !cond_rc) {
3747 			BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3748 			rc = -EINVAL;
3749 			goto error;
3750 		}
3751 next_iteration:
3752 		if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
3753 			BNXT_TF_DBG(ERR, "reject the flow\n");
3754 			rc = -EINVAL;
3755 			goto error;
3756 		} else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
3757 			uint32_t rf_idx;
3758 			uint64_t regval;
3759 
3760 			/* least significant 16 bits from reg_file index */
3761 			rf_idx = (uint32_t)(cond_goto & 0xFFFF);
3762 			if (!ulp_regfile_read(parms->regfile, rf_idx,
3763 					      &regval)) {
3764 				BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3765 					    rf_idx);
3766 				rc = -EINVAL;
3767 				goto error;
3768 			}
3769 			cond_goto = (int32_t)regval;
3770 		}
3771 
3772 		if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3773 			BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3774 				    cond_goto);
3775 			goto error;
3776 		}
3777 		tbl_idx += cond_goto;
3778 	}
3779 
3780 	return rc;
3781 error:
3782 	BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3783 		    ulp_mapper_tmpl_name_str(parms->tmpl_type),
3784 		    parms->dev_id, tid);
3785 	return rc;
3786 }
3787 
3788 static int32_t
ulp_mapper_resource_free(struct bnxt_ulp_context * ulp,uint32_t fid,struct ulp_flow_db_res_params * res)3789 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3790 			 uint32_t fid,
3791 			 struct ulp_flow_db_res_params *res)
3792 {
3793 	struct tf *tfp;
3794 	int32_t	rc = 0;
3795 
3796 	if (!res || !ulp) {
3797 		BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3798 		return -EINVAL;
3799 	}
3800 	if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION)
3801 		tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES);
3802 	else
3803 		tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO);
3804 	if (!tfp) {
3805 		BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3806 		return -EINVAL;
3807 	}
3808 
3809 	switch (res->resource_func) {
3810 	case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3811 		rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3812 		break;
3813 	case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3814 		rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3815 		break;
3816 	case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3817 		rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3818 		break;
3819 	case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3820 		rc = ulp_mapper_ident_free(ulp, tfp, res);
3821 		break;
3822 	case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3823 		rc = ulp_mapper_mark_free(ulp, res);
3824 		break;
3825 	case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3826 		rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3827 		break;
3828 	case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3829 		rc = ulp_mapper_child_flow_free(ulp, fid, res);
3830 		break;
3831 	case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3832 		rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3833 		break;
3834 	default:
3835 		break;
3836 	}
3837 
3838 	return rc;
3839 }
3840 
3841 int32_t
ulp_mapper_resources_free(struct bnxt_ulp_context * ulp_ctx,enum bnxt_ulp_fdb_type flow_type,uint32_t fid)3842 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3843 			  enum bnxt_ulp_fdb_type flow_type,
3844 			  uint32_t fid)
3845 {
3846 	struct ulp_flow_db_res_params res_parms = { 0 };
3847 	int32_t rc, trc;
3848 
3849 	if (!ulp_ctx) {
3850 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3851 		return -EINVAL;
3852 	}
3853 
3854 	/*
3855 	 * Set the critical resource on the first resource del, then iterate
3856 	 * while status is good
3857 	 */
3858 	res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3859 
3860 	rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3861 
3862 	if (rc) {
3863 		/*
3864 		 * This is unexpected on the first call to resource del.
3865 		 * It likely means that the flow did not exist in the flow db.
3866 		 */
3867 		BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3868 			    flow_type, fid, rc);
3869 		return rc;
3870 	}
3871 
3872 	while (!rc) {
3873 		trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3874 		if (trc)
3875 			/*
3876 			 * On fail, we still need to attempt to free the
3877 			 * remaining resources.  Don't return
3878 			 */
3879 			BNXT_TF_DBG(ERR,
3880 				    "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3881 				    "] failed rc=%d.\n",
3882 				    flow_type, fid, res_parms.resource_func,
3883 				    res_parms.resource_hndl, trc);
3884 
3885 		/* All subsequent call require the non-critical_resource */
3886 		res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3887 
3888 		rc = ulp_flow_db_resource_del(ulp_ctx,
3889 					      flow_type,
3890 					      fid,
3891 					      &res_parms);
3892 	}
3893 
3894 	/* Free the Flow ID since we've removed all resources */
3895 	rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3896 
3897 	return rc;
3898 }
3899 
3900 static void
ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_data * mapper_data)3901 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3902 				    struct bnxt_ulp_mapper_data *mapper_data)
3903 {
3904 	struct bnxt_ulp_mapper_glb_resource_entry *ent;
3905 	struct ulp_flow_db_res_params res;
3906 	uint32_t dir, idx;
3907 
3908 	/* Iterate the global resources and process each one */
3909 	for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3910 		for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) {
3911 			ent = &mapper_data->glb_res_tbl[dir][idx];
3912 			if (ent->resource_func ==
3913 			    BNXT_ULP_RESOURCE_FUNC_INVALID ||
3914 			    ent->shared)
3915 				continue;
3916 			memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3917 			res.resource_func = ent->resource_func;
3918 			res.direction = dir;
3919 			res.resource_type = ent->resource_type;
3920 			/*convert it from BE to cpu */
3921 			res.resource_hndl =
3922 				tfp_be_to_cpu_64(ent->resource_hndl);
3923 			ulp_mapper_resource_free(ulp_ctx, 0, &res);
3924 		}
3925 	}
3926 }
3927 
3928 int32_t
ulp_mapper_flow_destroy(struct bnxt_ulp_context * ulp_ctx,enum bnxt_ulp_fdb_type flow_type,uint32_t fid)3929 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3930 			enum bnxt_ulp_fdb_type flow_type,
3931 			uint32_t fid)
3932 {
3933 	int32_t rc;
3934 
3935 	if (!ulp_ctx) {
3936 		BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3937 		return -EINVAL;
3938 	}
3939 
3940 	rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3941 	return rc;
3942 }
3943 
3944 /* Function to handle the mapping of the Flow to be compatible
3945  * with the underlying hardware.
3946  */
3947 int32_t
ulp_mapper_flow_create(struct bnxt_ulp_context * ulp_ctx,struct bnxt_ulp_mapper_create_parms * cparms)3948 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3949 		       struct bnxt_ulp_mapper_create_parms *cparms)
3950 {
3951 	struct bnxt_ulp_mapper_parms parms;
3952 	struct ulp_regfile regfile;
3953 	int32_t	 rc = 0, trc;
3954 
3955 	if (!ulp_ctx || !cparms)
3956 		return -EINVAL;
3957 
3958 	/* Initialize the parms structure */
3959 	memset(&parms, 0, sizeof(parms));
3960 	parms.act_prop = cparms->act_prop;
3961 	parms.act_bitmap = cparms->act;
3962 	parms.hdr_bitmap = cparms->hdr_bitmap;
3963 	parms.enc_hdr_bitmap = cparms->enc_hdr_bitmap;
3964 	parms.regfile = &regfile;
3965 	parms.hdr_field = cparms->hdr_field;
3966 	parms.enc_field = cparms->enc_field;
3967 	parms.fld_bitmap = cparms->fld_bitmap;
3968 	parms.comp_fld = cparms->comp_fld;
3969 	parms.ulp_ctx = ulp_ctx;
3970 	parms.act_tid = cparms->act_tid;
3971 	parms.class_tid = cparms->class_tid;
3972 	parms.flow_type = cparms->flow_type;
3973 	parms.parent_flow = cparms->parent_flow;
3974 	parms.child_flow = cparms->child_flow;
3975 	parms.fid = cparms->flow_id;
3976 	parms.tun_idx = cparms->tun_idx;
3977 	parms.app_priority = cparms->app_priority;
3978 	parms.flow_pattern_id = cparms->flow_pattern_id;
3979 	parms.act_pattern_id = cparms->act_pattern_id;
3980 	parms.app_id = cparms->app_id;
3981 	parms.port_id = cparms->port_id;
3982 
3983 	/* Get the device id from the ulp context */
3984 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3985 		BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3986 		return -EINVAL;
3987 	}
3988 
3989 	/* Get the device params, it will be used in later processing */
3990 	parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3991 	if (!parms.device_params) {
3992 		BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3993 			    parms.dev_id);
3994 		return -EINVAL;
3995 	}
3996 
3997 	/*
3998 	 * Get the mapper data for dynamic mapper data such as default
3999 	 * ids.
4000 	 */
4001 	parms.mapper_data = (struct bnxt_ulp_mapper_data *)
4002 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4003 	if (!parms.mapper_data) {
4004 		BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
4005 		return -EINVAL;
4006 	}
4007 
4008 	/* initialize the registry file for further processing */
4009 	if (!ulp_regfile_init(parms.regfile)) {
4010 		BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
4011 		return -EINVAL;
4012 	}
4013 
4014 	/* Process the action template list from the selected action table*/
4015 	if (parms.act_tid) {
4016 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
4017 		/* Process the action template tables */
4018 		rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
4019 		if (rc)
4020 			goto flow_error;
4021 		cparms->shared_hndl = parms.shared_hndl;
4022 	}
4023 
4024 	if (parms.class_tid) {
4025 		parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
4026 
4027 		/* Process the class template tables.*/
4028 		rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
4029 		if (rc)
4030 			goto flow_error;
4031 	}
4032 
4033 	/* setup the parent-child details */
4034 	if (parms.parent_flow) {
4035 		/* create a parent flow details */
4036 		rc = ulp_flow_db_parent_flow_create(&parms);
4037 		if (rc)
4038 			goto flow_error;
4039 	} else if (parms.child_flow) {
4040 		/* create a child flow details */
4041 		rc = ulp_flow_db_child_flow_create(&parms);
4042 		if (rc)
4043 			goto flow_error;
4044 	}
4045 
4046 	return rc;
4047 
4048 flow_error:
4049 	/* Free all resources that were allocated during flow creation */
4050 	trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
4051 				      parms.fid);
4052 	if (trc)
4053 		BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
4054 
4055 	return rc;
4056 }
4057 
4058 int32_t
ulp_mapper_init(struct bnxt_ulp_context * ulp_ctx)4059 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
4060 {
4061 	struct bnxt_ulp_mapper_data *data;
4062 	struct tf *tfp;
4063 	int32_t rc;
4064 
4065 	if (!ulp_ctx)
4066 		return -EINVAL;
4067 
4068 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
4069 	if (!tfp)
4070 		return -EINVAL;
4071 
4072 	data = rte_zmalloc("ulp_mapper_data",
4073 			   sizeof(struct bnxt_ulp_mapper_data), 0);
4074 	if (!data) {
4075 		BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
4076 		return -ENOMEM;
4077 	}
4078 
4079 	if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
4080 		BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
4081 		/* Don't call deinit since the prof_func wasn't allocated. */
4082 		rte_free(data);
4083 		return -ENOMEM;
4084 	}
4085 
4086 	/* Allocate the global resource ids */
4087 	rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
4088 	if (rc) {
4089 		BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
4090 		goto error;
4091 	}
4092 
4093 	/*
4094 	 * Only initialize the app global resources if a shared session was
4095 	 * created.
4096 	 */
4097 	if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) {
4098 		rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data);
4099 		if (rc) {
4100 			BNXT_TF_DBG(ERR, "Failed to init app glb resources\n");
4101 			goto error;
4102 		}
4103 	}
4104 
4105 	/* Allocate the generic table list */
4106 	rc = ulp_mapper_generic_tbl_list_init(data);
4107 	if (rc) {
4108 		BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
4109 		goto error;
4110 	}
4111 
4112 	return 0;
4113 error:
4114 	/* Ignore the return code in favor of returning the original error. */
4115 	ulp_mapper_deinit(ulp_ctx);
4116 	return rc;
4117 }
4118 
4119 void
ulp_mapper_deinit(struct bnxt_ulp_context * ulp_ctx)4120 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
4121 {
4122 	struct bnxt_ulp_mapper_data *data;
4123 	struct tf *tfp;
4124 
4125 	if (!ulp_ctx) {
4126 		BNXT_TF_DBG(ERR,
4127 			    "Failed to acquire ulp context, so data may not be released.\n");
4128 		return;
4129 	}
4130 
4131 	data = (struct bnxt_ulp_mapper_data *)
4132 		bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
4133 	if (!data) {
4134 		/* Go ahead and return since there is no allocated data. */
4135 		BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
4136 		return;
4137 	}
4138 
4139 	tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
4140 	if (!tfp) {
4141 		BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
4142 		/* Free the mapper data regardless of errors. */
4143 		goto free_mapper_data;
4144 	}
4145 
4146 	/* Free the global resource info table entries */
4147 	ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
4148 
4149 free_mapper_data:
4150 	/* Free the generic table */
4151 	(void)ulp_mapper_generic_tbl_list_deinit(data);
4152 
4153 	rte_free(data);
4154 	/* Reset the data pointer within the ulp_ctx. */
4155 	bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
4156 }
4157