xref: /dpdk/drivers/net/bnxt/tf_core/v3/tfc_act.c (revision ca827d42ad72f90d045716e688b539e53e31a7cc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5 #include <stdio.h>
6 
7 #include "bnxt.h"
8 #include "bnxt_mpc.h"
9 
10 #include "tfc.h"
11 #include "cfa_bld_mpc_field_ids.h"
12 #include "cfa_bld_mpcops.h"
13 #include "tfo.h"
14 #include "tfc_em.h"
15 #include "tfc_cpm.h"
16 #include "tfc_msg.h"
17 #include "tfc_priv.h"
18 #include "cfa_types.h"
19 #include "cfa_mm.h"
20 #include "tfc_action_handle.h"
21 #include "sys_util.h"
22 #include "tfc_util.h"
23 
24 /*
25  * The read/write  granularity is 32B
26  */
27 #define TFC_ACT_RW_GRANULARITY 32
28 
29 #define TFC_ACT_CACHE_OPT_EN 0
30 
31 /* Max additional data size in bytes */
32 #define TFC_ACT_DISCARD_DATA_SIZE 128
33 
34 int tfc_act_alloc(struct tfc *tfcp,
35 		  uint8_t tsid,
36 		  struct tfc_cmm_info *cmm_info,
37 		  uint16_t num_contig_rec)
38 {
39 	int rc = 0;
40 	struct tfc_cpm *cpm_lkup = NULL;
41 	struct tfc_cpm *cpm_act = NULL;
42 	uint16_t pool_id;
43 	struct tfc_ts_mem_cfg mem_cfg;
44 	bool is_bs_owner;
45 	struct tfc_cmm *cmm;
46 	uint32_t entry_offset;
47 	struct cfa_mm_alloc_parms aparms;
48 	bool is_shared;
49 	struct tfc_ts_pool_info pi;
50 	bool valid;
51 	uint16_t max_pools;
52 
53 	rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, &max_pools);
54 	if (unlikely(rc)) {
55 		PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc));
56 		return -EINVAL;
57 	}
58 
59 	if (unlikely(!valid)) {
60 		PMD_DRV_LOG_LINE(ERR, "tsid(%d) not allocated", tsid);
61 		return -EINVAL;
62 	}
63 
64 	if (unlikely(max_pools == 0)) {
65 		PMD_DRV_LOG_LINE(ERR, "tsid(%d) Max pools must be greater than 0 %d",
66 				 tsid, max_pools);
67 		return -EINVAL;
68 	}
69 
70 	tfo_ts_get_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi);
71 
72 	/* Get CPM instances */
73 	rc = tfo_ts_get_cpm_inst(tfcp->tfo, tsid, cmm_info->dir, &cpm_lkup, &cpm_act);
74 	if (unlikely(rc)) {
75 		PMD_DRV_LOG_LINE(ERR, "failed to get CPM instances: %s",
76 				 strerror(-rc));
77 		return -EINVAL;
78 	}
79 
80 	rc = tfo_ts_get_mem_cfg(tfcp->tfo, tsid,
81 				cmm_info->dir,
82 				CFA_REGION_TYPE_ACT,
83 				&is_bs_owner,
84 				&mem_cfg);
85 	if (unlikely(rc)) {
86 		PMD_DRV_LOG_LINE(ERR, "tfo_ts_get_mem_cfg() failed: %s", strerror(-rc));
87 		return -EINVAL;
88 	}
89 
90 	/* if no pool available locally or all pools full */
91 	rc = tfc_cpm_get_avail_pool(cpm_act, &pool_id);
92 
93 	if (rc) {
94 		/* Allocate a pool */
95 		struct cfa_mm_query_parms qparms;
96 		struct cfa_mm_open_parms oparms;
97 		uint16_t fid;
98 
99 		/* There is only 1 pool for a non-shared table scope
100 		 * and it is full.
101 		 */
102 		if (unlikely(!is_shared)) {
103 			PMD_DRV_LOG_LINE(ERR, "no records remain");
104 			return -ENOMEM;
105 		}
106 		rc = tfc_get_fid(tfcp, &fid);
107 		if (unlikely(rc))
108 			return rc;
109 
110 		rc = tfc_tbl_scope_pool_alloc(tfcp,
111 					      fid,
112 					      tsid,
113 					      CFA_REGION_TYPE_ACT,
114 					      cmm_info->dir,
115 					      NULL,
116 					      &pool_id);
117 
118 		if (unlikely(rc)) {
119 			PMD_DRV_LOG_LINE(ERR, "table scope pool alloc failed: %s",
120 					 strerror(-rc));
121 			return -EINVAL;
122 		}
123 
124 		/* Create pool CMM instance */
125 		qparms.max_records = mem_cfg.rec_cnt;
126 		qparms.max_contig_records = pi.act_max_contig_rec;
127 		rc = cfa_mm_query(&qparms);
128 		if (unlikely(rc)) {
129 			PMD_DRV_LOG_LINE(ERR, "cfa_mm_query() failed: %s", strerror(-rc));
130 			return rc;
131 		}
132 
133 		cmm = rte_zmalloc("tf", qparms.db_size, 0);
134 		oparms.db_mem_size = qparms.db_size;
135 		oparms.max_contig_records = qparms.max_contig_records;
136 		oparms.max_records = qparms.max_records / max_pools;
137 		rc = cfa_mm_open(cmm, &oparms);
138 		if (unlikely(rc)) {
139 			PMD_DRV_LOG_LINE(ERR, "cfa_mm_open() failed: %d", rc);
140 			return -EINVAL;
141 		}
142 
143 		/* Store CMM instance in the CPM */
144 		rc = tfc_cpm_set_cmm_inst(cpm_act, pool_id, cmm);
145 		if (unlikely(rc)) {
146 			PMD_DRV_LOG_LINE(ERR, "tfc_cpm_set_cmm_inst() failed: %d", rc);
147 			return -EINVAL;
148 		}
149 		/* store updated pool info */
150 		tfo_ts_set_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi);
151 
152 	} else {
153 		/* Get the pool instance and allocate an act rec index from the pool */
154 		rc = tfc_cpm_get_cmm_inst(cpm_act, pool_id, &cmm);
155 		if (unlikely(rc)) {
156 			PMD_DRV_LOG_LINE(ERR, "tfc_cpm_get_cmm_inst() failed: %d", rc);
157 			return -EINVAL;
158 		}
159 	}
160 
161 	aparms.num_contig_records = 1 << next_pow2(num_contig_rec);
162 	rc = cfa_mm_alloc(cmm, &aparms);
163 	if (unlikely(rc)) {
164 		PMD_DRV_LOG_LINE(ERR, "cfa_mm_alloc() failed: %d", rc);
165 		return -EINVAL;
166 	}
167 
168 	/* Update CPM info so it will determine best pool to use next alloc */
169 	rc = tfc_cpm_set_usage(pi.act_cpm, pool_id, aparms.used_count, aparms.all_used);
170 	if (unlikely(rc))
171 		PMD_DRV_LOG_LINE(ERR, "EM insert tfc_cpm_set_usage() failed: %d", rc);
172 
173 	CREATE_OFFSET(&entry_offset, pi.act_pool_sz_exp, pool_id, aparms.record_offset);
174 
175 	/* Create Action handle */
176 	cmm_info->act_handle = tfc_create_action_handle(tsid,
177 							num_contig_rec,
178 							entry_offset);
179 	return rc;
180 }
181 
182 int tfc_act_set_response(struct cfa_bld_mpcinfo *mpc_info,
183 			 struct bnxt_mpc_mbuf *mpc_msg_out,
184 			 uint8_t *rx_msg)
185 {
186 	int rc;
187 	int i;
188 	struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_WRITE_CMP_MAX_FLD];
189 
190 	/* Process response */
191 	for (i = 0; i < CFA_BLD_MPC_WRITE_CMP_MAX_FLD; i++)
192 		fields_cmp[i].field_id = INVALID_U16;
193 
194 	fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].field_id =
195 		CFA_BLD_MPC_WRITE_CMP_STATUS_FLD;
196 
197 	rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_write(rx_msg,
198 							     mpc_msg_out->msg_size,
199 							     fields_cmp);
200 
201 	if (unlikely(rc)) {
202 		PMD_DRV_LOG_LINE(ERR, "write parse failed: %d", rc);
203 		rc = -EINVAL;
204 	}
205 
206 	if (unlikely(fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK)) {
207 		PMD_DRV_LOG_LINE(ERR, "failed with status code:%d",
208 				(uint32_t)fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val);
209 		rc = ((int)fields_cmp[CFA_BLD_MPC_WRITE_CMP_STATUS_FLD].val) * -1;
210 	}
211 
212 	return rc;
213 }
214 
215 int tfc_act_set(struct tfc *tfcp,
216 		struct tfc_mpc_batch_info_t *batch_info,
217 		const struct tfc_cmm_info *cmm_info,
218 		const uint8_t *data,
219 		uint16_t data_sz_words)
220 {
221 	int rc = 0;
222 	uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES];
223 	uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES];
224 	uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT;
225 	uint32_t i;
226 	uint32_t buff_len;
227 	struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_WRITE_CMD_MAX_FLD];
228 	uint32_t entry_offset;
229 	struct bnxt_mpc_mbuf mpc_msg_in;
230 	struct bnxt_mpc_mbuf mpc_msg_out;
231 	struct cfa_bld_mpcinfo *mpc_info;
232 	uint32_t record_size;
233 	uint8_t tsid;
234 	bool is_shared;
235 	bool valid;
236 
237 	tfo_mpcinfo_get(tfcp->tfo, &mpc_info);
238 
239 	/* Check that MPC APIs are bound */
240 	if (unlikely(mpc_info->mpcops == NULL)) {
241 		PMD_DRV_LOG_LINE(ERR, "MPC not initialized");
242 		return -EINVAL;
243 	}
244 
245 	tfc_get_fields_from_action_handle(&cmm_info->act_handle,
246 					  &tsid,
247 					  &record_size,
248 					  &entry_offset);
249 
250 	rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL);
251 	if (unlikely(rc)) {
252 		PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc));
253 		return -EINVAL;
254 	}
255 	if (unlikely(!valid)) {
256 		PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid);
257 		return -EINVAL;
258 	}
259 
260 	/* Create MPC EM insert command using builder */
261 	for (i = 0; i < CFA_BLD_MPC_WRITE_CMD_MAX_FLD; i++)
262 		fields_cmd[i].field_id = INVALID_U16;
263 
264 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD].field_id =
265 		CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD;
266 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_OPAQUE_FLD].val = 0xAA;
267 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD].field_id =
268 		CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD;
269 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_TYPE_FLD].val = CFA_BLD_MPC_HW_TABLE_TYPE_ACTION;
270 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD].field_id =
271 		CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD;
272 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_SCOPE_FLD].val = tsid;
273 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD].field_id =
274 		CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD;
275 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_DATA_SIZE_FLD].val = data_sz_words;
276 #if TFC_ACT_CACHE_OPT_EN
277 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD].field_id =
278 		CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD;
279 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_CACHE_OPTION_FLD].val = 0x01;
280 #endif
281 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD].field_id =
282 		CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD;
283 	fields_cmd[CFA_BLD_MPC_WRITE_CMD_TABLE_INDEX_FLD].val = entry_offset;
284 
285 	buff_len = TFC_MPC_MAX_TX_BYTES;
286 
287 	rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_write(tx_msg,
288 							     &buff_len,
289 							     data,
290 							     fields_cmd);
291 
292 	if (unlikely(rc)) {
293 		PMD_DRV_LOG_LINE(ERR, "write build failed: %d", rc);
294 		goto cleanup;
295 	}
296 
297 	/* Send MPC */
298 	mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ?
299 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA :
300 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA);
301 	mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES];
302 	mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES;
303 	mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT;
304 	mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES];
305 	mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES;
306 
307 	rc = tfc_mpc_send(tfcp->bp,
308 			  &mpc_msg_in,
309 			  &mpc_msg_out,
310 			  &msg_count,
311 			  TFC_MPC_TABLE_WRITE,
312 			  batch_info);
313 
314 	if (unlikely(rc)) {
315 		PMD_DRV_LOG_LINE(ERR, "write MPC send failed: %d", rc);
316 		goto cleanup;
317 	}
318 
319 	if (batch_info && !batch_info->enabled)
320 		rc =  tfc_act_set_response(mpc_info, &mpc_msg_out, rx_msg);
321 
322 	return rc;
323 
324  cleanup:
325 
326 	return rc;
327 }
328 
329 int tfc_act_get_only_response(struct cfa_bld_mpcinfo *mpc_info,
330 			      struct bnxt_mpc_mbuf *mpc_msg_out,
331 			      uint8_t *rx_msg,
332 			      uint16_t *data_sz_words)
333 {
334 	int i;
335 	int rc;
336 	uint8_t discard_data[TFC_ACT_DISCARD_DATA_SIZE];
337 	struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_READ_CMP_MAX_FLD] = { {0} };
338 
339 	/* Process response */
340 	for (i = 0; i < CFA_BLD_MPC_READ_CMP_MAX_FLD; i++)
341 		fields_cmp[i].field_id = INVALID_U16;
342 
343 	fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].field_id =
344 		CFA_BLD_MPC_READ_CMP_STATUS_FLD;
345 
346 	rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_read(rx_msg,
347 							    mpc_msg_out->msg_size,
348 							    discard_data,
349 							    *data_sz_words * TFC_MPC_BYTES_PER_WORD,
350 							    fields_cmp);
351 
352 	if (unlikely(rc)) {
353 		PMD_DRV_LOG_LINE(ERR, "Action read parse failed: %d", rc);
354 		return -1;
355 	}
356 
357 	if (fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK) {
358 		PMD_DRV_LOG_LINE(ERR, "Action read failed with status code:%d",
359 				 (uint32_t)fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val);
360 		rc = ((int)fields_cmp[CFA_BLD_MPC_READ_CMP_STATUS_FLD].val) * -1;
361 		return -1;
362 	}
363 
364 	return 0;
365 }
366 
367 static int tfc_act_get_only(struct tfc *tfcp,
368 			    struct tfc_mpc_batch_info_t *batch_info,
369 			    const struct tfc_cmm_info *cmm_info,
370 			    uint64_t *host_address,
371 			    uint16_t *data_sz_words)
372 {
373 	int rc = 0;
374 	uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES] = { 0 };
375 	uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES] = { 0 };
376 	uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT;
377 	int i;
378 	uint32_t buff_len;
379 	struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_READ_CMD_MAX_FLD] = { {0} };
380 	uint32_t entry_offset;
381 	struct bnxt_mpc_mbuf mpc_msg_in;
382 	struct bnxt_mpc_mbuf mpc_msg_out;
383 	uint32_t record_size;
384 	uint8_t tsid;
385 	bool is_shared;
386 	struct cfa_bld_mpcinfo *mpc_info;
387 	bool valid;
388 
389 	tfo_mpcinfo_get(tfcp->tfo, &mpc_info);
390 
391 	tfc_get_fields_from_action_handle(&cmm_info->act_handle,
392 					  &tsid,
393 					  &record_size,
394 					  &entry_offset);
395 
396 	rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL);
397 	if (unlikely(rc)) {
398 		PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc));
399 		return -EINVAL;
400 	}
401 	if (unlikely(!valid)) {
402 		PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid);
403 		return -EINVAL;
404 	}
405 
406 	/* Check that data pointer is word aligned */
407 	if (unlikely(*host_address  & 0x3ULL)) {
408 		PMD_DRV_LOG_LINE(ERR, "data pointer not word aligned");
409 		return -EINVAL;
410 	}
411 
412 	/* Check that MPC APIs are bound */
413 	if (unlikely(mpc_info->mpcops == NULL)) {
414 		PMD_DRV_LOG_LINE(ERR, "MPC not initialized");
415 		return -EINVAL;
416 	}
417 
418 	/* Create MPC EM insert command using builder */
419 	for (i = 0; i < CFA_BLD_MPC_READ_CMD_MAX_FLD; i++)
420 		fields_cmd[i].field_id = INVALID_U16;
421 
422 	fields_cmd[CFA_BLD_MPC_READ_CMD_OPAQUE_FLD].field_id =
423 		CFA_BLD_MPC_READ_CMD_OPAQUE_FLD;
424 	fields_cmd[CFA_BLD_MPC_READ_CMD_OPAQUE_FLD].val = 0xAA;
425 
426 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD].field_id =
427 		CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD;
428 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_TYPE_FLD].val =
429 		CFA_BLD_MPC_HW_TABLE_TYPE_ACTION;
430 
431 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD].field_id =
432 		CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD;
433 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_SCOPE_FLD].val = tsid;
434 
435 	fields_cmd[CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD].field_id =
436 		CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD;
437 	fields_cmd[CFA_BLD_MPC_READ_CMD_DATA_SIZE_FLD].val = *data_sz_words;
438 
439 #if TFC_ACT_CACHE_OPT_EN
440 	fields_cmd[CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD].field_id =
441 		CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD;
442 	fields_cmd[CFA_BLD_MPC_READ_CMD_CACHE_OPTION_FLD].val = 0x0;
443 #endif
444 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD].field_id =
445 		CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD;
446 	fields_cmd[CFA_BLD_MPC_READ_CMD_TABLE_INDEX_FLD].val = entry_offset;
447 
448 	fields_cmd[CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD].field_id =
449 		CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD;
450 	fields_cmd[CFA_BLD_MPC_READ_CMD_HOST_ADDRESS_FLD].val = *host_address;
451 
452 	buff_len = TFC_MPC_MAX_TX_BYTES;
453 
454 	rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_read(tx_msg,
455 							    &buff_len,
456 							    fields_cmd);
457 
458 	if (unlikely(rc)) {
459 		PMD_DRV_LOG_LINE(ERR, "read build failed: %d", rc);
460 		goto cleanup;
461 	}
462 
463 	/* Send MPC */
464 	mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ?
465 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA :
466 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA);
467 	mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES];
468 	mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES;
469 	mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT;
470 	mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES];
471 	mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES;
472 
473 	rc = tfc_mpc_send(tfcp->bp,
474 			  &mpc_msg_in,
475 			  &mpc_msg_out,
476 			  &msg_count,
477 			  TFC_MPC_TABLE_READ,
478 			  batch_info);
479 
480 	if (unlikely(rc)) {
481 		PMD_DRV_LOG_LINE(ERR, "read MPC send failed: %d", rc);
482 		goto cleanup;
483 	}
484 
485 	if ((batch_info && !batch_info->enabled) || !batch_info) {
486 		rc = tfc_act_get_only_response(mpc_info,
487 					       &mpc_msg_out,
488 					       rx_msg,
489 					       data_sz_words);
490 		if (rc) {
491 			PMD_DRV_LOG_LINE(ERR, "Action response failed: %d", rc);
492 			goto cleanup;
493 		}
494 	} else {
495 		batch_info->comp_info[batch_info->count - 1].read_words = *data_sz_words;
496 	}
497 
498 	return 0;
499 
500  cleanup:
501 
502 	return rc;
503 }
504 
505 int tfc_act_get_clear_response(struct cfa_bld_mpcinfo *mpc_info,
506 			       struct bnxt_mpc_mbuf *mpc_msg_out,
507 			       uint8_t *rx_msg,
508 			       uint16_t *data_sz_words)
509 {
510 	int i;
511 	int rc;
512 	uint8_t discard_data[TFC_ACT_DISCARD_DATA_SIZE];
513 	struct cfa_mpc_data_obj fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_MAX_FLD] = { {0} };
514 
515 	/* Process response */
516 	for (i = 0; i < CFA_BLD_MPC_READ_CLR_CMP_MAX_FLD; i++)
517 		fields_cmp[i].field_id = INVALID_U16;
518 
519 	fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].field_id =
520 		CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD;
521 
522 	rc = mpc_info->mpcops->cfa_bld_mpc_parse_cache_read_clr(rx_msg,
523 								mpc_msg_out->msg_size,
524 								discard_data,
525 								*data_sz_words *
526 								TFC_MPC_BYTES_PER_WORD,
527 								fields_cmp);
528 
529 	if (unlikely(rc)) {
530 		PMD_DRV_LOG_LINE(ERR, "Action read clear parse failed: %d", rc);
531 		return -1;
532 	}
533 
534 	if (fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val != CFA_BLD_MPC_OK) {
535 		PMD_DRV_LOG_LINE(ERR, "Action read clear failed with status code:%d",
536 				 (uint32_t)fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val);
537 		rc = ((int)fields_cmp[CFA_BLD_MPC_READ_CLR_CMP_STATUS_FLD].val) * -1;
538 		return rc;
539 	}
540 
541 	return 0;
542 }
543 
544 static int tfc_act_get_clear(struct tfc *tfcp,
545 			     struct tfc_mpc_batch_info_t *batch_info,
546 			     const struct tfc_cmm_info *cmm_info,
547 			     uint64_t *host_address,
548 			     uint16_t *data_sz_words,
549 			     uint8_t clr_offset,
550 			     uint8_t clr_size)
551 {
552 	int rc = 0;
553 	uint8_t tx_msg[TFC_MPC_MAX_TX_BYTES] = { 0 };
554 	uint8_t rx_msg[TFC_MPC_MAX_RX_BYTES] = { 0 };
555 	uint32_t msg_count = BNXT_MPC_COMP_MSG_COUNT;
556 	int i;
557 	uint32_t buff_len;
558 	struct cfa_mpc_data_obj fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_MAX_FLD] = { {0} };
559 	uint32_t entry_offset;
560 	struct bnxt_mpc_mbuf mpc_msg_in;
561 	struct bnxt_mpc_mbuf mpc_msg_out;
562 	uint32_t record_size;
563 	uint8_t tsid;
564 	bool is_shared;
565 	struct cfa_bld_mpcinfo *mpc_info;
566 	bool valid;
567 	uint16_t mask = 0;
568 
569 	tfo_mpcinfo_get(tfcp->tfo, &mpc_info);
570 
571 	tfc_get_fields_from_action_handle(&cmm_info->act_handle,
572 					  &tsid,
573 					  &record_size,
574 					  &entry_offset);
575 
576 	rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL);
577 	if (unlikely(rc)) {
578 		PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s",
579 				 strerror(-rc));
580 		return -EINVAL;
581 	}
582 	if (unlikely(!valid)) {
583 		PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid);
584 		return -EINVAL;
585 	}
586 
587 	/* Check that data pointer is word aligned */
588 	if (unlikely(*host_address  & 0x3ULL)) {
589 		PMD_DRV_LOG_LINE(ERR, "data pointer not word aligned");
590 		return -EINVAL;
591 	}
592 
593 	/* Check that MPC APIs are bound */
594 	if (unlikely(mpc_info->mpcops == NULL)) {
595 		PMD_DRV_LOG_LINE(ERR, "MPC not initialized");
596 		return -EINVAL;
597 	}
598 
599 	/* Create MPC EM insert command using builder */
600 	for (i = 0; i < CFA_BLD_MPC_READ_CLR_CMD_MAX_FLD; i++)
601 		fields_cmd[i].field_id = INVALID_U16;
602 
603 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD].field_id =
604 		CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD;
605 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_OPAQUE_FLD].val = 0xAA;
606 
607 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD].field_id =
608 		CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD;
609 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_TYPE_FLD].val =
610 		CFA_BLD_MPC_HW_TABLE_TYPE_ACTION;
611 
612 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD].field_id =
613 		CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD;
614 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_SCOPE_FLD].val = tsid;
615 
616 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD].field_id =
617 		CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD;
618 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_DATA_SIZE_FLD].val = *data_sz_words;
619 
620 #if TFC_ACT_CACHE_OPT_EN
621 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD].field_id =
622 		CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD;
623 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CACHE_OPTION_FLD].val = 0x0;
624 #endif
625 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD].field_id =
626 		CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD;
627 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_TABLE_INDEX_FLD].val = entry_offset;
628 
629 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD].field_id =
630 		CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD;
631 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_HOST_ADDRESS_FLD].val = *host_address;
632 
633 	for (i = clr_offset; i < clr_size; i++)
634 		mask |= (1 << i);
635 
636 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD].field_id =
637 		CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD;
638 	fields_cmd[CFA_BLD_MPC_READ_CLR_CMD_CLEAR_MASK_FLD].val = mask;
639 
640 	buff_len = TFC_MPC_MAX_TX_BYTES;
641 
642 	rc = mpc_info->mpcops->cfa_bld_mpc_build_cache_read_clr(tx_msg,
643 								&buff_len,
644 								fields_cmd);
645 
646 	if (unlikely(rc)) {
647 		PMD_DRV_LOG_LINE(ERR, "read clear build failed: %d", rc);
648 		goto cleanup;
649 	}
650 
651 	/* Send MPC */
652 	mpc_msg_in.chnl_id = (cmm_info->dir == CFA_DIR_TX ?
653 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_TE_CFA :
654 			      HWRM_RING_ALLOC_INPUT_MPC_CHNLS_TYPE_RE_CFA);
655 	mpc_msg_in.msg_data = &tx_msg[TFC_MPC_HEADER_SIZE_BYTES];
656 	mpc_msg_in.msg_size = buff_len - TFC_MPC_HEADER_SIZE_BYTES;
657 	mpc_msg_out.cmp_type = CMPL_BASE_TYPE_MID_PATH_SHORT;
658 	mpc_msg_out.msg_data = &rx_msg[TFC_MPC_HEADER_SIZE_BYTES];
659 	mpc_msg_out.msg_size = TFC_MPC_MAX_RX_BYTES;
660 
661 	rc = tfc_mpc_send(tfcp->bp,
662 			  &mpc_msg_in,
663 			  &mpc_msg_out,
664 			  &msg_count,
665 			  TFC_MPC_TABLE_READ_CLEAR,
666 			  batch_info);
667 
668 	if (unlikely(rc)) {
669 		PMD_DRV_LOG_LINE(ERR, "read clear MPC send failed: %d", rc);
670 		goto cleanup;
671 	}
672 
673 	if ((batch_info && !batch_info->enabled) || !batch_info) {
674 		rc = tfc_act_get_clear_response(mpc_info,
675 						&mpc_msg_out,
676 						rx_msg,
677 						data_sz_words);
678 		if (rc) {
679 			PMD_DRV_LOG_LINE(ERR, "Action response failed: %d", rc);
680 			goto cleanup;
681 		}
682 	} else {
683 		batch_info->comp_info[batch_info->count - 1].read_words = *data_sz_words;
684 	}
685 
686 	return 0;
687 
688  cleanup:
689 
690 	return rc;
691 }
692 
693 int tfc_act_get(struct tfc *tfcp,
694 		struct tfc_mpc_batch_info_t *batch_info,
695 		const struct tfc_cmm_info *cmm_info,
696 		struct tfc_cmm_clr *clr,
697 		uint64_t *host_address,
698 		uint16_t *data_sz_words)
699 {
700 	/* It's not an error to pass clr as a Null pointer, just means that read
701 	 * and clear is not being requested.  Also allow the user to manage
702 	 * clear via the clr flag.
703 	 */
704 	if (clr && clr->clr) {
705 		/* Clear offset and size have to be two bytes aligned */
706 		if (clr->offset_in_byte % 2 || clr->sz_in_byte % 2) {
707 			PMD_DRV_LOG_LINE(ERR,
708 					 "clr offset(%d) or size(%d) is not two bytes aligned",
709 					 clr->offset_in_byte, clr->sz_in_byte);
710 			return -EINVAL;
711 		}
712 
713 		return tfc_act_get_clear(tfcp,
714 					 batch_info,
715 					 cmm_info,
716 					 host_address,
717 					 data_sz_words,
718 					 clr->offset_in_byte / 2,
719 					 clr->sz_in_byte / 2);
720 	} else {
721 		return tfc_act_get_only(tfcp,
722 					batch_info,
723 					cmm_info,
724 					host_address,
725 					data_sz_words);
726 	}
727 }
728 
729 int tfc_act_free(struct tfc *tfcp,
730 		 const struct tfc_cmm_info *cmm_info)
731 {
732 	int rc = 0;
733 	struct tfc_cpm *cpm_lkup = NULL;
734 	struct tfc_cpm *cpm_act = NULL;
735 	struct tfc_cmm *cmm;
736 	uint32_t pool_id;
737 	struct tfc_ts_pool_info pi;
738 	uint32_t record_size;
739 	uint32_t record_offset;
740 	struct cfa_mm_free_parms fparms;
741 	uint8_t tsid;
742 	bool is_shared;
743 	bool valid;
744 	bool is_bs_owner;
745 	struct tfc_ts_mem_cfg mem_cfg;
746 
747 	/* Get fields from MPC Action handle */
748 	tfc_get_fields_from_action_handle(&cmm_info->act_handle,
749 					  &tsid,
750 					  &record_size,
751 					  &record_offset);
752 
753 	rc = tfo_ts_get(tfcp->tfo, tsid, &is_shared, NULL, &valid, NULL);
754 	if (unlikely(rc)) {
755 		PMD_DRV_LOG_LINE(ERR, "failed to get tsid: %s", strerror(-rc));
756 		return -EINVAL;
757 	}
758 	if (unlikely(!valid)) {
759 		PMD_DRV_LOG_LINE(ERR, "tsid not allocated %d", tsid);
760 		return -EINVAL;
761 	}
762 	tfo_ts_get_pool_info(tfcp->tfo, tsid, cmm_info->dir, &pi);
763 
764 	pool_id = TFC_ACTION_GET_POOL_ID(record_offset, pi.act_pool_sz_exp);
765 
766 	rc = tfo_ts_get_mem_cfg(tfcp->tfo, tsid,
767 				cmm_info->dir,
768 				CFA_REGION_TYPE_ACT,
769 				&is_bs_owner,
770 				&mem_cfg);   /* Gets rec_cnt */
771 	if (unlikely(rc)) {
772 		PMD_DRV_LOG_LINE(ERR, "tfo_ts_get_mem_cfg() failed: %s",
773 				 strerror(-rc));
774 		return -EINVAL;
775 	}
776 
777 	/* Get CPM instance for this table scope */
778 	rc = tfo_ts_get_cpm_inst(tfcp->tfo, tsid, cmm_info->dir, &cpm_lkup, &cpm_act);
779 	if (unlikely(rc)) {
780 		PMD_DRV_LOG_LINE(ERR, "failed to get CPM instance: %d", rc);
781 		return -EINVAL;
782 	}
783 
784 	rc = tfc_cpm_get_cmm_inst(cpm_act, pool_id, &cmm);
785 	if (unlikely(rc)) {
786 		PMD_DRV_LOG_LINE(ERR, "failed to get CMM instance: %d", rc);
787 		return -EINVAL;
788 	}
789 
790 	fparms.record_offset = record_offset;
791 	fparms.num_contig_records = 1 << next_pow2(record_size);
792 	rc = cfa_mm_free(cmm, &fparms);
793 	if (unlikely(rc)) {
794 		PMD_DRV_LOG_LINE(ERR, "failed to free record: %d", rc);
795 		return -EINVAL;
796 	}
797 
798 	rc = tfc_cpm_set_usage(cpm_act, pool_id, 0, false);
799 	if (unlikely(rc))
800 		PMD_DRV_LOG_LINE(ERR, "failed to set usage: %d", rc);
801 
802 	return rc;
803 }
804