xref: /dpdk/drivers/common/cnxk/roc_npc.c (revision 29fd052d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "roc_api.h"
6 #include "roc_priv.h"
7 
8 int
9 roc_npc_vtag_actions_get(struct roc_npc *roc_npc)
10 {
11 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
12 
13 	return npc->vtag_strip_actions;
14 }
15 
16 int
17 roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
18 {
19 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
20 
21 	npc->vtag_strip_actions -= count;
22 	return npc->vtag_strip_actions;
23 }
24 
25 int
26 roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id)
27 {
28 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
29 
30 	return npc_mcam_free_counter(npc, ctr_id);
31 }
32 
33 int
34 roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id,
35 			  uint64_t *count)
36 {
37 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
38 
39 	return npc_mcam_read_counter(npc, ctr_id, count);
40 }
41 
42 int
43 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
44 {
45 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
46 
47 	return npc_mcam_clear_counter(npc, ctr_id);
48 }
49 
50 int
51 roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry)
52 {
53 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
54 
55 	return npc_mcam_free_entry(npc, entry);
56 }
57 
58 int
59 roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc)
60 {
61 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
62 
63 	return npc_flow_free_all_resources(npc);
64 }
65 
66 int
67 roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry,
68 			   int *alloc_entry, int req_count, int priority,
69 			   int *resp_count)
70 {
71 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
72 
73 	return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count,
74 				      priority, resp_count);
75 }
76 
77 int
78 roc_npc_mcam_enable_all_entries(struct roc_npc *roc_npc, bool enable)
79 {
80 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
81 
82 	return npc_flow_enable_all_entries(npc, enable);
83 }
84 
85 int
86 roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
87 			 struct roc_npc_flow *ref_mcam, int prio,
88 			 int *resp_count)
89 {
90 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
91 
92 	return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count);
93 }
94 
95 int
96 roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
97 			   bool enable)
98 {
99 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
100 
101 	return npc_mcam_ena_dis_entry(npc, mcam, enable);
102 }
103 
104 int
105 roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam)
106 {
107 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
108 
109 	return npc_mcam_write_entry(npc, mcam);
110 }
111 
112 int
113 roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
114 {
115 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
116 
117 	if (roc_model_is_cn10k())
118 		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
119 	else if (roc_model_is_cn98xx())
120 		return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1);
121 	else
122 		return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1);
123 }
124 
125 static int
126 npc_mcam_tot_entries(void)
127 {
128 	/* FIXME: change to reading in AF from NPC_AF_CONST1/2
129 	 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
130 	 */
131 	if (roc_model_is_cn10k() || roc_model_is_cn98xx())
132 		return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
133 	else
134 		return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
135 }
136 
137 const char *
138 roc_npc_profile_name_get(struct roc_npc *roc_npc)
139 {
140 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
141 
142 	return (char *)npc->profile_name;
143 }
144 
145 int
146 roc_npc_init(struct roc_npc *roc_npc)
147 {
148 	uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL;
149 	struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
150 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
151 	uint32_t bmap_sz;
152 	int rc = 0, idx;
153 	size_t sz;
154 
155 	PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ);
156 
157 	memset(npc, 0, sizeof(*npc));
158 	npc->mbox = (&nix->dev)->mbox;
159 	roc_npc->channel = nix->rx_chan_base;
160 	roc_npc->pf_func = (&nix->dev)->pf_func;
161 	npc->channel = roc_npc->channel;
162 	npc->pf_func = roc_npc->pf_func;
163 	npc->flow_max_priority = roc_npc->flow_max_priority;
164 	npc->switch_header_type = roc_npc->switch_header_type;
165 	npc->flow_prealloc_size = roc_npc->flow_prealloc_size;
166 
167 	if (npc->mbox == NULL)
168 		return NPC_ERR_PARAM;
169 
170 	rc = npc_mcam_fetch_kex_cfg(npc);
171 	if (rc)
172 		goto done;
173 
174 	roc_npc->kex_capability = npc_get_kex_capability(npc);
175 	roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX];
176 
177 	npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
178 
179 	/* Free, free_rev, live and live_rev entries */
180 	bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
181 	mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0);
182 	if (mem == NULL) {
183 		plt_err("Bmap alloc failed");
184 		rc = NPC_ERR_NO_MEM;
185 		return rc;
186 	}
187 
188 	sz = npc->flow_max_priority * sizeof(struct npc_flow_list);
189 	npc->flow_list = plt_zmalloc(sz, 0);
190 	if (npc->flow_list == NULL) {
191 		plt_err("flow_list alloc failed");
192 		rc = NPC_ERR_NO_MEM;
193 		goto done;
194 	}
195 
196 	sz = npc->flow_max_priority * sizeof(struct npc_prio_flow_list_head);
197 	npc->prio_flow_list = plt_zmalloc(sz, 0);
198 	if (npc->prio_flow_list == NULL) {
199 		plt_err("prio_flow_list alloc failed");
200 		rc = NPC_ERR_NO_MEM;
201 		goto done;
202 	}
203 
204 	npc_mem = mem;
205 	for (idx = 0; idx < npc->flow_max_priority; idx++) {
206 		TAILQ_INIT(&npc->flow_list[idx]);
207 		TAILQ_INIT(&npc->prio_flow_list[idx]);
208 	}
209 
210 	npc->rss_grps = NPC_RSS_GRPS;
211 
212 	bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps);
213 	nix_mem = plt_zmalloc(bmap_sz, 0);
214 	if (nix_mem == NULL) {
215 		plt_err("Bmap alloc failed");
216 		rc = NPC_ERR_NO_MEM;
217 		goto done;
218 	}
219 
220 	npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz);
221 
222 	if (!npc->rss_grp_entries) {
223 		plt_err("bitmap init failed");
224 		rc = NPC_ERR_NO_MEM;
225 		goto done;
226 	}
227 
228 	/* Group 0 will be used for RSS,
229 	 * 1 -7 will be used for npc_flow RSS action
230 	 */
231 	plt_bitmap_set(npc->rss_grp_entries, 0);
232 
233 	return rc;
234 
235 done:
236 	if (npc->flow_list)
237 		plt_free(npc->flow_list);
238 	if (npc->prio_flow_list)
239 		plt_free(npc->prio_flow_list);
240 	if (npc_mem)
241 		plt_free(npc_mem);
242 	return rc;
243 }
244 
245 int
246 roc_npc_fini(struct roc_npc *roc_npc)
247 {
248 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
249 	int rc;
250 
251 	rc = npc_flow_free_all_resources(npc);
252 	if (rc) {
253 		plt_err("Error when deleting NPC MCAM entries, counters");
254 		return rc;
255 	}
256 
257 	if (npc->flow_list) {
258 		plt_free(npc->flow_list);
259 		npc->flow_list = NULL;
260 	}
261 
262 	if (npc->prio_flow_list) {
263 		plt_free(npc->prio_flow_list);
264 		npc->prio_flow_list = NULL;
265 	}
266 
267 	return 0;
268 }
269 
270 int
271 roc_npc_validate_portid_action(struct roc_npc *roc_npc_src,
272 			       struct roc_npc *roc_npc_dst)
273 {
274 	struct roc_nix *roc_nix_src = roc_npc_src->roc_nix;
275 	struct nix *nix_src = roc_nix_to_nix_priv(roc_nix_src);
276 	struct roc_nix *roc_nix_dst = roc_npc_dst->roc_nix;
277 	struct nix *nix_dst = roc_nix_to_nix_priv(roc_nix_dst);
278 
279 	if (roc_nix_is_pf(roc_npc_dst->roc_nix)) {
280 		plt_err("Output port should be VF");
281 		return -EINVAL;
282 	}
283 
284 	if (nix_dst->dev.vf >= nix_src->dev.maxvf) {
285 		plt_err("Invalid VF for output port");
286 		return -EINVAL;
287 	}
288 
289 	if (nix_src->dev.pf != nix_dst->dev.pf) {
290 		plt_err("Output port should be VF of ingress PF");
291 		return -EINVAL;
292 	}
293 	return 0;
294 }
295 
296 static int
297 npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
298 		  const struct roc_npc_action actions[],
299 		  struct roc_npc_flow *flow)
300 {
301 	const struct roc_npc_action_port_id *act_portid;
302 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
303 	const struct roc_npc_action_mark *act_mark;
304 	const struct roc_npc_action_meter *act_mtr;
305 	const struct roc_npc_action_queue *act_q;
306 	const struct roc_npc_action_vf *vf_act;
307 	bool vlan_insert_action = false;
308 	int sel_act, req_act = 0;
309 	uint16_t pf_func, vf_id;
310 	int errcode = 0;
311 	int mark = 0;
312 	int rq = 0;
313 
314 	/* Initialize actions */
315 	flow->ctr_id = NPC_COUNTER_NONE;
316 	flow->mtr_id = ROC_NIX_MTR_ID_INVALID;
317 	pf_func = npc->pf_func;
318 
319 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
320 		switch (actions->type) {
321 		case ROC_NPC_ACTION_TYPE_VOID:
322 			break;
323 		case ROC_NPC_ACTION_TYPE_MARK:
324 			act_mark = (const struct roc_npc_action_mark *)
325 					   actions->conf;
326 			if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) {
327 				plt_err("mark value must be < 0xfffe");
328 				goto err_exit;
329 			}
330 			mark = act_mark->id + 1;
331 			req_act |= ROC_NPC_ACTION_TYPE_MARK;
332 			break;
333 
334 		case ROC_NPC_ACTION_TYPE_FLAG:
335 			mark = NPC_FLOW_FLAG_VAL;
336 			req_act |= ROC_NPC_ACTION_TYPE_FLAG;
337 			break;
338 
339 		case ROC_NPC_ACTION_TYPE_COUNT:
340 			/* Indicates, need a counter */
341 			flow->ctr_id = 1;
342 			req_act |= ROC_NPC_ACTION_TYPE_COUNT;
343 			break;
344 
345 		case ROC_NPC_ACTION_TYPE_DROP:
346 			req_act |= ROC_NPC_ACTION_TYPE_DROP;
347 			break;
348 
349 		case ROC_NPC_ACTION_TYPE_PF:
350 			req_act |= ROC_NPC_ACTION_TYPE_PF;
351 			pf_func &= (0xfc00);
352 			break;
353 
354 		case ROC_NPC_ACTION_TYPE_VF:
355 			vf_act =
356 				(const struct roc_npc_action_vf *)actions->conf;
357 			req_act |= ROC_NPC_ACTION_TYPE_VF;
358 			vf_id = vf_act->id & RVU_PFVF_FUNC_MASK;
359 			pf_func &= (0xfc00);
360 			pf_func = (pf_func | (vf_id + 1));
361 			break;
362 
363 		case ROC_NPC_ACTION_TYPE_PORT_ID:
364 			act_portid = (const struct roc_npc_action_port_id *)
365 					     actions->conf;
366 			pf_func &= (0xfc00);
367 			pf_func = (pf_func | (act_portid->id + 1));
368 			req_act |= ROC_NPC_ACTION_TYPE_VF;
369 			break;
370 
371 		case ROC_NPC_ACTION_TYPE_QUEUE:
372 			act_q = (const struct roc_npc_action_queue *)
373 					actions->conf;
374 			rq = act_q->index;
375 			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
376 			break;
377 
378 		case ROC_NPC_ACTION_TYPE_RSS:
379 			req_act |= ROC_NPC_ACTION_TYPE_RSS;
380 			break;
381 
382 		case ROC_NPC_ACTION_TYPE_SEC:
383 			/* Assumes user has already configured security
384 			 * session for this flow. Associated conf is
385 			 * opaque. When security is implemented,
386 			 * we need to verify that for specified security
387 			 * session:
388 			 *  action_type ==
389 			 *    NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL &&
390 			 *  session_protocol ==
391 			 *    NPC_SECURITY_PROTOCOL_IPSEC
392 			 */
393 			req_act |= ROC_NPC_ACTION_TYPE_SEC;
394 			rq = 0;
395 
396 			/* Special processing when with inline device */
397 			if (roc_nix_inb_is_with_inl_dev(roc_npc->roc_nix) &&
398 			    roc_nix_inl_dev_is_probed()) {
399 				rq = 0;
400 				pf_func = nix_inl_dev_pffunc_get();
401 			}
402 			break;
403 		case ROC_NPC_ACTION_TYPE_VLAN_STRIP:
404 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP;
405 			break;
406 		case ROC_NPC_ACTION_TYPE_VLAN_INSERT:
407 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT;
408 			break;
409 		case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT:
410 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
411 			break;
412 		case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT:
413 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
414 			break;
415 		case ROC_NPC_ACTION_TYPE_METER:
416 			act_mtr = (const struct roc_npc_action_meter *)
417 					  actions->conf;
418 			flow->mtr_id = act_mtr->mtr_id;
419 			req_act |= ROC_NPC_ACTION_TYPE_METER;
420 			break;
421 		default:
422 			errcode = NPC_ERR_ACTION_NOTSUP;
423 			goto err_exit;
424 		}
425 	}
426 
427 	if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT |
428 		       ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
429 		       ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT))
430 		vlan_insert_action = true;
431 
432 	if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT |
433 			ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
434 			ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) ==
435 	    ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
436 		plt_err("PCP insert action can't be supported alone");
437 		errcode = NPC_ERR_ACTION_NOTSUP;
438 		goto err_exit;
439 	}
440 
441 	/* Both STRIP and INSERT actions are not supported */
442 	if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) {
443 		errcode = NPC_ERR_ACTION_NOTSUP;
444 		goto err_exit;
445 	}
446 
447 	/* Check if actions specified are compatible */
448 	if (attr->egress) {
449 		if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
450 			plt_err("VLAN pop action is not supported on Egress");
451 			errcode = NPC_ERR_ACTION_NOTSUP;
452 			goto err_exit;
453 		}
454 
455 		if (req_act &
456 		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT |
457 		      ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
458 		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT |
459 		      ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) {
460 			plt_err("Only VLAN insert, drop, count supported on Egress");
461 			errcode = NPC_ERR_ACTION_NOTSUP;
462 			goto err_exit;
463 		}
464 
465 		if (vlan_insert_action &&
466 		    (req_act & ROC_NPC_ACTION_TYPE_DROP)) {
467 			plt_err("Both VLAN insert and drop actions cannot be supported");
468 			errcode = NPC_ERR_ACTION_NOTSUP;
469 			goto err_exit;
470 		}
471 
472 		if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
473 			flow->npc_action = NIX_TX_ACTIONOP_DROP;
474 		} else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) ||
475 			   vlan_insert_action) {
476 			flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT;
477 		} else {
478 			plt_err("Unsupported action for egress");
479 			errcode = NPC_ERR_ACTION_NOTSUP;
480 			goto err_exit;
481 		}
482 
483 		goto set_pf_func;
484 	} else {
485 		if (vlan_insert_action) {
486 			errcode = NPC_ERR_ACTION_NOTSUP;
487 			goto err_exit;
488 		}
489 	}
490 
491 	/* We have already verified the attr, this is ingress.
492 	 * - Exactly one terminating action is supported
493 	 * - Exactly one of MARK or FLAG is supported
494 	 * - If terminating action is DROP, only count is valid.
495 	 */
496 	sel_act = req_act & NPC_ACTION_TERM;
497 	if ((sel_act & (sel_act - 1)) != 0) {
498 		errcode = NPC_ERR_ACTION_NOTSUP;
499 		goto err_exit;
500 	}
501 
502 	if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
503 		sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT;
504 		if ((sel_act & (sel_act - 1)) != 0) {
505 			errcode = NPC_ERR_ACTION_NOTSUP;
506 			goto err_exit;
507 		}
508 	}
509 
510 	if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) ==
511 	    (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
512 		errcode = NPC_ERR_ACTION_NOTSUP;
513 		goto err_exit;
514 	}
515 
516 	if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)
517 		npc->vtag_strip_actions++;
518 
519 	/* Set NIX_RX_ACTIONOP */
520 	if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
521 		/* Only VLAN action is provided */
522 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
523 	} else if (req_act &
524 		   (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) {
525 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
526 		if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
527 			flow->npc_action |= (uint64_t)rq << 20;
528 	} else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
529 		flow->npc_action = NIX_RX_ACTIONOP_DROP;
530 	} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
531 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
532 		flow->npc_action |= (uint64_t)rq << 20;
533 	} else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
534 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
535 	} else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {
536 		flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC;
537 		flow->npc_action |= (uint64_t)rq << 20;
538 	} else if (req_act &
539 		   (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
540 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
541 	} else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) {
542 		/* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end
543 		 * This is default action, when user specify only
544 		 * COUNT ACTION
545 		 */
546 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
547 	} else {
548 		/* Should never reach here */
549 		errcode = NPC_ERR_ACTION_NOTSUP;
550 		goto err_exit;
551 	}
552 
553 	if (mark)
554 		flow->npc_action |= (uint64_t)mark << 40;
555 
556 set_pf_func:
557 	/* Ideally AF must ensure that correct pf_func is set */
558 	flow->npc_action |= (uint64_t)pf_func << 4;
559 
560 	return 0;
561 
562 err_exit:
563 	return errcode;
564 }
565 
566 typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst);
567 
568 static int
569 npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[],
570 		  struct roc_npc_flow *flow, struct npc_parse_state *pst)
571 {
572 	npc_parse_stage_func_t parse_stage_funcs[] = {
573 		npc_parse_meta_items, npc_parse_pre_l2, npc_parse_cpt_hdr,
574 		npc_parse_higig2_hdr, npc_parse_la,	npc_parse_lb,
575 		npc_parse_lc,	      npc_parse_ld,	npc_parse_le,
576 		npc_parse_lf,	      npc_parse_lg,	npc_parse_lh,
577 	};
578 	uint8_t layer = 0;
579 	int key_offset;
580 	int rc;
581 
582 	if (pattern == NULL)
583 		return NPC_ERR_PARAM;
584 
585 	memset(pst, 0, sizeof(*pst));
586 	pst->npc = npc;
587 	pst->flow = flow;
588 
589 	/* Use integral byte offset */
590 	key_offset = pst->npc->keyx_len[flow->nix_intf];
591 	key_offset = (key_offset + 7) / 8;
592 
593 	/* Location where LDATA would begin */
594 	pst->mcam_data = (uint8_t *)flow->mcam_data;
595 	pst->mcam_mask = (uint8_t *)flow->mcam_mask;
596 
597 	while (pattern->type != ROC_NPC_ITEM_TYPE_END &&
598 	       layer < PLT_DIM(parse_stage_funcs)) {
599 		/* Skip place-holders */
600 		pattern = npc_parse_skip_void_and_any_items(pattern);
601 
602 		pst->pattern = pattern;
603 		rc = parse_stage_funcs[layer](pst);
604 		if (rc != 0)
605 			return rc;
606 
607 		layer++;
608 
609 		/*
610 		 * Parse stage function sets pst->pattern to
611 		 * 1 past the last item it consumed.
612 		 */
613 		pattern = pst->pattern;
614 
615 		if (pst->terminate)
616 			break;
617 	}
618 
619 	/* Skip trailing place-holders */
620 	pattern = npc_parse_skip_void_and_any_items(pattern);
621 
622 	/* Are there more items than what we can handle? */
623 	if (pattern->type != ROC_NPC_ITEM_TYPE_END)
624 		return NPC_ERR_PATTERN_NOTSUP;
625 
626 	return 0;
627 }
628 
629 static int
630 npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr,
631 	       struct roc_npc_flow *flow)
632 {
633 	if (attr == NULL)
634 		return NPC_ERR_PARAM;
635 	else if (attr->priority >= npc->flow_max_priority)
636 		return NPC_ERR_PARAM;
637 	else if ((!attr->egress && !attr->ingress) ||
638 		 (attr->egress && attr->ingress))
639 		return NPC_ERR_PARAM;
640 
641 	if (attr->ingress)
642 		flow->nix_intf = ROC_NPC_INTF_RX;
643 	else
644 		flow->nix_intf = ROC_NPC_INTF_TX;
645 
646 	flow->priority = attr->priority;
647 	return 0;
648 }
649 
650 static int
651 npc_parse_rule(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
652 	       const struct roc_npc_item_info pattern[],
653 	       const struct roc_npc_action actions[], struct roc_npc_flow *flow,
654 	       struct npc_parse_state *pst)
655 {
656 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
657 	int err;
658 
659 	/* Check attr */
660 	err = npc_parse_attr(npc, attr, flow);
661 	if (err)
662 		return err;
663 
664 	/* Check pattern */
665 	err = npc_parse_pattern(npc, pattern, flow, pst);
666 	if (err)
667 		return err;
668 
669 	/* Check action */
670 	err = npc_parse_actions(roc_npc, attr, actions, flow);
671 	if (err)
672 		return err;
673 	return 0;
674 }
675 
676 int
677 roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
678 		   const struct roc_npc_item_info pattern[],
679 		   const struct roc_npc_action actions[],
680 		   struct roc_npc_flow *flow)
681 {
682 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
683 	struct npc_parse_state parse_state = {0};
684 	int rc;
685 
686 	rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow,
687 			    &parse_state);
688 	if (rc)
689 		return rc;
690 
691 	parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
692 
693 	return npc_program_mcam(npc, &parse_state, 0);
694 }
695 
696 int
697 npc_rss_free_grp_get(struct npc *npc, uint32_t *pos)
698 {
699 	struct plt_bitmap *bmap = npc->rss_grp_entries;
700 
701 	for (*pos = 0; *pos < ROC_NIX_RSS_GRPS; ++*pos) {
702 		if (!plt_bitmap_get(bmap, *pos))
703 			break;
704 	}
705 	return *pos < ROC_NIX_RSS_GRPS ? 0 : -1;
706 }
707 
708 int
709 npc_rss_action_configure(struct roc_npc *roc_npc,
710 			 const struct roc_npc_action_rss *rss, uint8_t *alg_idx,
711 			 uint32_t *rss_grp, uint32_t mcam_id)
712 {
713 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
714 	struct roc_nix *roc_nix = roc_npc->roc_nix;
715 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
716 	uint32_t flowkey_cfg, rss_grp_idx, i, rem;
717 	uint8_t key[ROC_NIX_RSS_KEY_LEN];
718 	const uint8_t *key_ptr;
719 	uint8_t flowkey_algx;
720 	uint16_t *reta;
721 	int rc;
722 
723 	rc = npc_rss_free_grp_get(npc, &rss_grp_idx);
724 	/* RSS group :0 is not usable for flow rss action */
725 	if (rc < 0 || rss_grp_idx == 0)
726 		return -ENOSPC;
727 
728 	for (i = 0; i < rss->queue_num; i++) {
729 		if (rss->queue[i] >= nix->nb_rx_queues) {
730 			plt_err("queue id > max number of queues");
731 			return -EINVAL;
732 		}
733 	}
734 
735 	*rss_grp = rss_grp_idx;
736 
737 	if (rss->key == NULL) {
738 		roc_nix_rss_key_default_fill(roc_nix, key);
739 		key_ptr = key;
740 	} else {
741 		key_ptr = rss->key;
742 	}
743 
744 	roc_nix_rss_key_set(roc_nix, key_ptr);
745 
746 	/* If queue count passed in the rss action is less than
747 	 * HW configured reta size, replicate rss action reta
748 	 * across HW reta table.
749 	 */
750 	reta = nix->reta[rss_grp_idx];
751 
752 	if (rss->queue_num > nix->reta_sz) {
753 		plt_err("too many queues for RSS context");
754 		return -ENOTSUP;
755 	}
756 
757 	for (i = 0; i < (nix->reta_sz / rss->queue_num); i++)
758 		memcpy(reta + i * rss->queue_num, rss->queue,
759 		       sizeof(uint16_t) * rss->queue_num);
760 
761 	rem = nix->reta_sz % rss->queue_num;
762 	if (rem)
763 		memcpy(&reta[i * rss->queue_num], rss->queue,
764 		       rem * sizeof(uint16_t));
765 
766 	rc = roc_nix_rss_reta_set(roc_nix, *rss_grp, reta);
767 	if (rc) {
768 		plt_err("Failed to init rss table rc = %d", rc);
769 		return rc;
770 	}
771 
772 	flowkey_cfg = roc_npc->flowkey_cfg_state;
773 
774 	rc = roc_nix_rss_flowkey_set(roc_nix, &flowkey_algx, flowkey_cfg,
775 				     *rss_grp, mcam_id);
776 	if (rc) {
777 		plt_err("Failed to set rss hash function rc = %d", rc);
778 		return rc;
779 	}
780 
781 	*alg_idx = flowkey_algx;
782 
783 	plt_bitmap_set(npc->rss_grp_entries, *rss_grp);
784 
785 	return 0;
786 }
787 
788 int
789 npc_rss_action_program(struct roc_npc *roc_npc,
790 		       const struct roc_npc_action actions[],
791 		       struct roc_npc_flow *flow)
792 {
793 	const struct roc_npc_action_rss *rss;
794 	uint32_t rss_grp;
795 	uint8_t alg_idx;
796 	int rc;
797 
798 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
799 		if (actions->type == ROC_NPC_ACTION_TYPE_RSS) {
800 			rss = (const struct roc_npc_action_rss *)actions->conf;
801 			rc = npc_rss_action_configure(roc_npc, rss, &alg_idx,
802 						      &rss_grp, flow->mcam_id);
803 			if (rc)
804 				return rc;
805 
806 			flow->npc_action &= (~(0xfULL));
807 			flow->npc_action |= NIX_RX_ACTIONOP_RSS;
808 			flow->npc_action |=
809 				((uint64_t)(alg_idx & NPC_RSS_ACT_ALG_MASK)
810 				 << NPC_RSS_ACT_ALG_OFFSET) |
811 				((uint64_t)(rss_grp & NPC_RSS_ACT_GRP_MASK)
812 				 << NPC_RSS_ACT_GRP_OFFSET);
813 			break;
814 		}
815 	}
816 	return 0;
817 }
818 
819 static int
820 npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
821 {
822 	struct roc_nix *roc_nix = roc_npc->roc_nix;
823 	struct nix_vtag_config *vtag_cfg;
824 	struct nix_vtag_config_rsp *rsp;
825 	struct mbox *mbox;
826 	struct nix *nix;
827 	int rc = 0;
828 
829 	union {
830 		uint64_t reg;
831 		struct nix_tx_vtag_action_s act;
832 	} tx_vtag_action;
833 
834 	nix = roc_nix_to_nix_priv(roc_nix);
835 	mbox = (&nix->dev)->mbox;
836 
837 	tx_vtag_action.reg = flow->vtag_action;
838 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
839 
840 	if (vtag_cfg == NULL)
841 		return -ENOSPC;
842 
843 	vtag_cfg->cfg_type = VTAG_TX;
844 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
845 	vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def;
846 	vtag_cfg->tx.free_vtag0 = true;
847 
848 	if (flow->vtag_insert_count == 2) {
849 		vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def;
850 		vtag_cfg->tx.free_vtag1 = true;
851 	}
852 
853 	rc = mbox_process_msg(mbox, (void *)&rsp);
854 	if (rc)
855 		return rc;
856 
857 	return 0;
858 }
859 
860 static int
861 npc_vtag_insert_action_parse(const struct roc_npc_action actions[],
862 			     struct roc_npc_flow *flow,
863 			     struct npc_action_vtag_info *vlan_info,
864 			     int *parsed_cnt)
865 {
866 	bool vlan_id_found = false, ethtype_found = false, pcp_found = false;
867 	int count = 0;
868 
869 	*parsed_cnt = 0;
870 
871 	/* This function parses parameters of one VLAN. When a parameter is
872 	 * found repeated, it treats it as the end of first VLAN's parameters
873 	 * and returns. The caller calls again to parse the parameters of the
874 	 * second VLAN.
875 	 */
876 
877 	for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) {
878 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
879 			if (vlan_id_found)
880 				return 0;
881 
882 			const struct roc_npc_action_of_set_vlan_vid *vtag =
883 				(const struct roc_npc_action_of_set_vlan_vid *)
884 					actions->conf;
885 
886 			vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid);
887 
888 			if (vlan_info->vlan_id > 0xfff) {
889 				plt_err("Invalid vlan_id for set vlan action");
890 				return -EINVAL;
891 			}
892 
893 			flow->vtag_insert_enabled = true;
894 			(*parsed_cnt)++;
895 			vlan_id_found = true;
896 		} else if (actions->type ==
897 			   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) {
898 			if (ethtype_found)
899 				return 0;
900 
901 			const struct roc_npc_action_of_push_vlan *ethtype =
902 				(const struct roc_npc_action_of_push_vlan *)
903 					actions->conf;
904 			vlan_info->vlan_ethtype =
905 				plt_be_to_cpu_16(ethtype->ethertype);
906 			if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN &&
907 			    vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) {
908 				plt_err("Invalid ethtype specified for push"
909 					" vlan action");
910 				return -EINVAL;
911 			}
912 			flow->vtag_insert_enabled = true;
913 			(*parsed_cnt)++;
914 			ethtype_found = true;
915 		} else if (actions->type ==
916 			   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
917 			if (pcp_found)
918 				return 0;
919 			const struct roc_npc_action_of_set_vlan_pcp *pcp =
920 				(const struct roc_npc_action_of_set_vlan_pcp *)
921 					actions->conf;
922 			vlan_info->vlan_pcp = pcp->vlan_pcp;
923 			if (vlan_info->vlan_pcp > 0x7) {
924 				plt_err("Invalid PCP value for pcp action");
925 				return -EINVAL;
926 			}
927 			flow->vtag_insert_enabled = true;
928 			(*parsed_cnt)++;
929 			pcp_found = true;
930 		} else {
931 			return 0;
932 		}
933 	}
934 
935 	return 0;
936 }
937 
938 static int
939 npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow,
940 				 struct npc_action_vtag_info *vlan_info)
941 {
942 	struct nix_vtag_config *vtag_cfg;
943 	struct nix_vtag_config_rsp *rsp;
944 	int rc = 0;
945 
946 	union {
947 		uint64_t reg;
948 		struct nix_tx_vtag_action_s act;
949 	} tx_vtag_action;
950 
951 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
952 
953 	if (vtag_cfg == NULL)
954 		return -ENOSPC;
955 
956 	vtag_cfg->cfg_type = VTAG_TX;
957 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
958 	vtag_cfg->tx.vtag0 =
959 		(((uint32_t)vlan_info[0].vlan_ethtype << 16) |
960 		 (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id);
961 
962 	vtag_cfg->tx.cfg_vtag0 = 1;
963 
964 	if (flow->vtag_insert_count == 2) {
965 		vtag_cfg->tx.vtag1 =
966 			(((uint32_t)vlan_info[1].vlan_ethtype << 16) |
967 			 (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id);
968 
969 		vtag_cfg->tx.cfg_vtag1 = 1;
970 	}
971 
972 	rc = mbox_process_msg(mbox, (void *)&rsp);
973 	if (rc)
974 		return rc;
975 
976 	if (rsp->vtag0_idx < 0 ||
977 	    ((flow->vtag_insert_count == 2) && (rsp->vtag1_idx < 0))) {
978 		plt_err("Failed to config TX VTAG action");
979 		return -EINVAL;
980 	}
981 
982 	tx_vtag_action.reg = 0;
983 	tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
984 	tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
985 	tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
986 	tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR;
987 
988 	if (flow->vtag_insert_count == 2) {
989 		tx_vtag_action.act.vtag1_def = rsp->vtag1_idx;
990 		tx_vtag_action.act.vtag1_lid = NPC_LID_LA;
991 		tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT;
992 		/* NIX_TX_VTAG_ACTION_S
993 		 *  If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte
994 		 *  offset accordingly. Thus, if the two offsets are equal in
995 		 *  the structure, hardware inserts Vtag 1 immediately after
996 		 *  Vtag 0 in the packet.
997 		 */
998 		tx_vtag_action.act.vtag1_relptr =
999 			NIX_TX_VTAGACTION_VTAG0_RELPTR;
1000 	}
1001 
1002 	flow->vtag_action = tx_vtag_action.reg;
1003 
1004 	return 0;
1005 }
1006 
1007 static int
1008 npc_vtag_strip_action_configure(struct mbox *mbox,
1009 				const struct roc_npc_action actions[],
1010 				struct roc_npc_flow *flow, int *strip_cnt)
1011 {
1012 	struct nix_vtag_config *vtag_cfg;
1013 	uint64_t rx_vtag_action = 0;
1014 	int count = 0, rc = 0;
1015 
1016 	*strip_cnt = 0;
1017 
1018 	for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) {
1019 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP)
1020 			(*strip_cnt)++;
1021 	}
1022 
1023 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
1024 
1025 	if (vtag_cfg == NULL)
1026 		return -ENOSPC;
1027 
1028 	vtag_cfg->cfg_type = VTAG_RX;
1029 	vtag_cfg->rx.strip_vtag = 1;
1030 	/* Always capture */
1031 	vtag_cfg->rx.capture_vtag = 1;
1032 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
1033 	vtag_cfg->rx.vtag_type = 0;
1034 
1035 	rc = mbox_process(mbox);
1036 	if (rc)
1037 		return rc;
1038 
1039 	rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
1040 	rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8);
1041 	rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
1042 
1043 	if (*strip_cnt == 2) {
1044 		rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47);
1045 		rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40);
1046 		rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32;
1047 	}
1048 	flow->vtag_action = rx_vtag_action;
1049 
1050 	return 0;
1051 }
1052 
1053 static int
1054 npc_vtag_action_program(struct roc_npc *roc_npc,
1055 			const struct roc_npc_action actions[],
1056 			struct roc_npc_flow *flow)
1057 {
1058 	bool vlan_strip_parsed = false, vlan_insert_parsed = false;
1059 	const struct roc_npc_action *insert_actions;
1060 	struct roc_nix *roc_nix = roc_npc->roc_nix;
1061 	struct npc_action_vtag_info vlan_info[2];
1062 	int parsed_cnt = 0, strip_cnt = 0;
1063 	int tot_vlan_params = 0;
1064 	struct mbox *mbox;
1065 	struct nix *nix;
1066 	int i, rc;
1067 
1068 	nix = roc_nix_to_nix_priv(roc_nix);
1069 	mbox = (&nix->dev)->mbox;
1070 
1071 	memset(vlan_info, 0, sizeof(vlan_info));
1072 
1073 	flow->vtag_insert_enabled = false;
1074 
1075 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
1076 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
1077 			if (vlan_strip_parsed) {
1078 				plt_err("Incorrect VLAN strip actions");
1079 				return -EINVAL;
1080 			}
1081 			rc = npc_vtag_strip_action_configure(mbox, actions,
1082 							     flow, &strip_cnt);
1083 			if (rc)
1084 				return rc;
1085 
1086 			if (strip_cnt == 2)
1087 				actions++;
1088 
1089 			vlan_strip_parsed = true;
1090 		} else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT ||
1091 			   actions->type ==
1092 				   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT ||
1093 			   actions->type ==
1094 				   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
1095 			if (vlan_insert_parsed) {
1096 				plt_err("Incorrect VLAN insert actions");
1097 				return -EINVAL;
1098 			}
1099 
1100 			insert_actions = actions;
1101 
1102 			for (i = 0; i < 2; i++) {
1103 				rc = npc_vtag_insert_action_parse(
1104 					insert_actions, flow, &vlan_info[i],
1105 					&parsed_cnt);
1106 
1107 				if (rc)
1108 					return rc;
1109 
1110 				if (parsed_cnt) {
1111 					insert_actions += parsed_cnt;
1112 					tot_vlan_params += parsed_cnt;
1113 					flow->vtag_insert_count++;
1114 				}
1115 			}
1116 			actions += tot_vlan_params - 1;
1117 			vlan_insert_parsed = true;
1118 		}
1119 	}
1120 
1121 	if (flow->vtag_insert_enabled) {
1122 		rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info);
1123 
1124 		if (rc)
1125 			return rc;
1126 	}
1127 	return 0;
1128 }
1129 
1130 struct roc_npc_flow *
1131 roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
1132 		    const struct roc_npc_item_info pattern[],
1133 		    const struct roc_npc_action actions[], int *errcode)
1134 {
1135 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1136 	struct roc_npc_flow *flow, *flow_iter;
1137 	struct npc_parse_state parse_state;
1138 	struct npc_flow_list *list;
1139 	int rc;
1140 
1141 	npc->channel = roc_npc->channel;
1142 	npc->is_sdp_link = roc_nix_is_sdp(roc_npc->roc_nix);
1143 	if (npc->is_sdp_link) {
1144 		if (roc_npc->is_sdp_mask_set) {
1145 			npc->sdp_channel = roc_npc->sdp_channel;
1146 			npc->sdp_channel_mask = roc_npc->sdp_channel_mask;
1147 		} else {
1148 			/* By default set the channel and mask to cover
1149 			 * the whole SDP channel range.
1150 			 */
1151 			npc->sdp_channel = (uint16_t)NIX_CHAN_SDP_CH_START;
1152 			npc->sdp_channel_mask = (uint16_t)NIX_CHAN_SDP_CH_START;
1153 		}
1154 	}
1155 
1156 	flow = plt_zmalloc(sizeof(*flow), 0);
1157 	if (flow == NULL) {
1158 		*errcode = NPC_ERR_NO_MEM;
1159 		return NULL;
1160 	}
1161 	memset(flow, 0, sizeof(*flow));
1162 
1163 	rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow,
1164 			    &parse_state);
1165 	if (rc != 0) {
1166 		*errcode = rc;
1167 		goto err_exit;
1168 	}
1169 
1170 	rc = npc_vtag_action_program(roc_npc, actions, flow);
1171 	if (rc != 0) {
1172 		*errcode = rc;
1173 		goto err_exit;
1174 	}
1175 
1176 	parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
1177 
1178 	rc = npc_program_mcam(npc, &parse_state, 1);
1179 	if (rc != 0) {
1180 		*errcode = rc;
1181 		goto err_exit;
1182 	}
1183 
1184 	rc = npc_rss_action_program(roc_npc, actions, flow);
1185 	if (rc != 0) {
1186 		*errcode = rc;
1187 		goto set_rss_failed;
1188 	}
1189 
1190 	list = &npc->flow_list[flow->priority];
1191 	/* List in ascending order of mcam entries */
1192 	TAILQ_FOREACH(flow_iter, list, next) {
1193 		if (flow_iter->mcam_id > flow->mcam_id) {
1194 			TAILQ_INSERT_BEFORE(flow_iter, flow, next);
1195 			return flow;
1196 		}
1197 	}
1198 
1199 	TAILQ_INSERT_TAIL(list, flow, next);
1200 	return flow;
1201 
1202 set_rss_failed:
1203 	rc = npc_mcam_free_entry(npc, flow->mcam_id);
1204 	if (rc != 0) {
1205 		*errcode = rc;
1206 		plt_free(flow);
1207 		return NULL;
1208 	}
1209 err_exit:
1210 	plt_free(flow);
1211 	return NULL;
1212 }
1213 
1214 int
1215 npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow)
1216 {
1217 	uint32_t rss_grp;
1218 
1219 	if ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_RSS) {
1220 		rss_grp = (flow->npc_action >> NPC_RSS_ACT_GRP_OFFSET) &
1221 			  NPC_RSS_ACT_GRP_MASK;
1222 		if (rss_grp == 0 || rss_grp >= npc->rss_grps)
1223 			return -EINVAL;
1224 
1225 		plt_bitmap_clear(npc->rss_grp_entries, rss_grp);
1226 	}
1227 
1228 	return 0;
1229 }
1230 
1231 int
1232 roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
1233 {
1234 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1235 	int rc;
1236 
1237 	rc = npc_rss_group_free(npc, flow);
1238 	if (rc != 0) {
1239 		plt_err("Failed to free rss action rc = %d", rc);
1240 		return rc;
1241 	}
1242 
1243 	if (flow->vtag_insert_enabled) {
1244 		rc = npc_vtag_cfg_delete(roc_npc, flow);
1245 		if (rc != 0)
1246 			return rc;
1247 	}
1248 
1249 	if (flow->ctr_id != NPC_COUNTER_NONE) {
1250 		rc = roc_npc_mcam_clear_counter(roc_npc, flow->ctr_id);
1251 		if (rc != 0)
1252 			return rc;
1253 
1254 		rc = npc_mcam_free_counter(npc, flow->ctr_id);
1255 		if (rc != 0)
1256 			return rc;
1257 	}
1258 
1259 	rc = npc_mcam_free_entry(npc, flow->mcam_id);
1260 	if (rc != 0)
1261 		return rc;
1262 
1263 	TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next);
1264 
1265 	npc_delete_prio_list_entry(npc, flow);
1266 
1267 	plt_free(flow);
1268 	return 0;
1269 }
1270 
1271 void
1272 roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc)
1273 {
1274 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1275 	struct roc_npc_flow *flow_iter;
1276 	struct npc_flow_list *list;
1277 	uint32_t max_prio, i;
1278 
1279 	max_prio = npc->flow_max_priority;
1280 
1281 	for (i = 0; i < max_prio; i++) {
1282 		list = &npc->flow_list[i];
1283 
1284 		/* List in ascending order of mcam entries */
1285 		TAILQ_FOREACH(flow_iter, list, next) {
1286 			roc_npc_flow_mcam_dump(file, roc_npc, flow_iter);
1287 		}
1288 	}
1289 }
1290 
1291 int
1292 roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc,
1293 				      struct roc_npc_flow *flow)
1294 {
1295 	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
1296 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1297 	struct mcam_entry *base_entry;
1298 	int idx, rc;
1299 
1300 	if (roc_nix_is_pf(roc_npc->roc_nix))
1301 		return 0;
1302 
1303 	(void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox);
1304 	rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp);
1305 	if (rc) {
1306 		plt_err("Failed to fetch VF's base MCAM entry");
1307 		return rc;
1308 	}
1309 	base_entry = &base_rule_rsp->entry_data;
1310 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
1311 		flow->mcam_data[idx] |= base_entry->kw[idx];
1312 		flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
1313 	}
1314 
1315 	return 0;
1316 }
1317