xref: /dpdk/drivers/common/cnxk/roc_npc.c (revision 29a8df5cb664feb6f182c07868c49c0f5c9a4c46)
1a07f7cedSKiran Kumar K /* SPDX-License-Identifier: BSD-3-Clause
2a07f7cedSKiran Kumar K  * Copyright(C) 2021 Marvell.
3a07f7cedSKiran Kumar K  */
4a07f7cedSKiran Kumar K 
5a07f7cedSKiran Kumar K #include "roc_api.h"
6a07f7cedSKiran Kumar K #include "roc_priv.h"
7a07f7cedSKiran Kumar K 
8a07f7cedSKiran Kumar K int
98a44b2a5SHanumanth Pothula roc_npc_mark_actions_get(struct roc_npc *roc_npc)
108a44b2a5SHanumanth Pothula {
118a44b2a5SHanumanth Pothula 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
128a44b2a5SHanumanth Pothula 
138a44b2a5SHanumanth Pothula 	return npc->mark_actions;
148a44b2a5SHanumanth Pothula }
158a44b2a5SHanumanth Pothula 
168a44b2a5SHanumanth Pothula int
178a44b2a5SHanumanth Pothula roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
188a44b2a5SHanumanth Pothula {
198a44b2a5SHanumanth Pothula 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
208a44b2a5SHanumanth Pothula 
218a44b2a5SHanumanth Pothula 	npc->mark_actions -= count;
228a44b2a5SHanumanth Pothula 	return npc->mark_actions;
238a44b2a5SHanumanth Pothula }
248a44b2a5SHanumanth Pothula 
258a44b2a5SHanumanth Pothula int
2619f3cc23SSatheesh Paul roc_npc_vtag_actions_get(struct roc_npc *roc_npc)
2719f3cc23SSatheesh Paul {
2819f3cc23SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
2919f3cc23SSatheesh Paul 
308ca851cdSSatheesh Paul 	return npc->vtag_strip_actions;
3119f3cc23SSatheesh Paul }
3219f3cc23SSatheesh Paul 
3319f3cc23SSatheesh Paul int
3419f3cc23SSatheesh Paul roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count)
3519f3cc23SSatheesh Paul {
3619f3cc23SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
3719f3cc23SSatheesh Paul 
388ca851cdSSatheesh Paul 	npc->vtag_strip_actions -= count;
398ca851cdSSatheesh Paul 	return npc->vtag_strip_actions;
4019f3cc23SSatheesh Paul }
4119f3cc23SSatheesh Paul 
4219f3cc23SSatheesh Paul int
43a07f7cedSKiran Kumar K roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id)
44a07f7cedSKiran Kumar K {
45a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
46a07f7cedSKiran Kumar K 
47df5cf15fSKiran Kumar K 	return npc_mcam_free_counter(npc->mbox, ctr_id);
48df5cf15fSKiran Kumar K }
49df5cf15fSKiran Kumar K 
50df5cf15fSKiran Kumar K int
51df5cf15fSKiran Kumar K roc_npc_inl_mcam_read_counter(uint32_t ctr_id, uint64_t *count)
52df5cf15fSKiran Kumar K {
53df5cf15fSKiran Kumar K 	struct nix_inl_dev *inl_dev = NULL;
54df5cf15fSKiran Kumar K 	struct idev_cfg *idev;
55df5cf15fSKiran Kumar K 
56df5cf15fSKiran Kumar K 	idev = idev_get_cfg();
57df5cf15fSKiran Kumar K 	if (idev)
58df5cf15fSKiran Kumar K 		inl_dev = idev->nix_inl_dev;
59df5cf15fSKiran Kumar K 	if (!inl_dev)
60df5cf15fSKiran Kumar K 		return 0;
61df5cf15fSKiran Kumar K 	return npc_mcam_read_counter(inl_dev->dev.mbox, ctr_id, count);
62df5cf15fSKiran Kumar K }
63df5cf15fSKiran Kumar K 
64df5cf15fSKiran Kumar K int
65df5cf15fSKiran Kumar K roc_npc_inl_mcam_clear_counter(uint32_t ctr_id)
66df5cf15fSKiran Kumar K {
67df5cf15fSKiran Kumar K 	struct nix_inl_dev *inl_dev = NULL;
68df5cf15fSKiran Kumar K 	struct idev_cfg *idev;
69df5cf15fSKiran Kumar K 
70df5cf15fSKiran Kumar K 	idev = idev_get_cfg();
71df5cf15fSKiran Kumar K 	if (idev)
72df5cf15fSKiran Kumar K 		inl_dev = idev->nix_inl_dev;
73df5cf15fSKiran Kumar K 	if (!inl_dev)
74df5cf15fSKiran Kumar K 		return 0;
75df5cf15fSKiran Kumar K 
76df5cf15fSKiran Kumar K 	return npc_mcam_clear_counter(inl_dev->dev.mbox, ctr_id);
77a07f7cedSKiran Kumar K }
78a07f7cedSKiran Kumar K 
79a07f7cedSKiran Kumar K int
80df29c91cSHarman Kalra roc_npc_mcam_alloc_counter(struct roc_npc *roc_npc, uint16_t *ctr_id)
81df29c91cSHarman Kalra {
82df29c91cSHarman Kalra 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
83df29c91cSHarman Kalra 
84df29c91cSHarman Kalra 	return npc_mcam_alloc_counter(npc->mbox, ctr_id);
85df29c91cSHarman Kalra }
86df29c91cSHarman Kalra 
87df29c91cSHarman Kalra int
88df29c91cSHarman Kalra roc_npc_get_free_mcam_entry(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
89df29c91cSHarman Kalra {
90df29c91cSHarman Kalra 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
91df29c91cSHarman Kalra 
92df29c91cSHarman Kalra 	return npc_get_free_mcam_entry(npc->mbox, flow, npc);
93df29c91cSHarman Kalra }
94df29c91cSHarman Kalra 
95df29c91cSHarman Kalra int
96df29c91cSHarman Kalra roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *count)
97a07f7cedSKiran Kumar K {
98a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
99a07f7cedSKiran Kumar K 
100df5cf15fSKiran Kumar K 	return npc_mcam_read_counter(npc->mbox, ctr_id, count);
101a07f7cedSKiran Kumar K }
102a07f7cedSKiran Kumar K 
103a07f7cedSKiran Kumar K int
104a07f7cedSKiran Kumar K roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
105a07f7cedSKiran Kumar K {
106a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
107a07f7cedSKiran Kumar K 
108df5cf15fSKiran Kumar K 	return npc_mcam_clear_counter(npc->mbox, ctr_id);
109a07f7cedSKiran Kumar K }
110a07f7cedSKiran Kumar K 
111a07f7cedSKiran Kumar K int
112a07f7cedSKiran Kumar K roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry)
113a07f7cedSKiran Kumar K {
114a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
115a07f7cedSKiran Kumar K 
116df5cf15fSKiran Kumar K 	return npc_mcam_free_entry(npc->mbox, entry);
117a07f7cedSKiran Kumar K }
118a07f7cedSKiran Kumar K 
119a07f7cedSKiran Kumar K int
12022d9d348SSatheesh Paul roc_npc_mcam_free(struct roc_npc *roc_npc, struct roc_npc_flow *mcam)
12122d9d348SSatheesh Paul {
12222d9d348SSatheesh Paul 	int rc = 0;
12322d9d348SSatheesh Paul 
12422d9d348SSatheesh Paul 	if (mcam->use_ctr) {
12522d9d348SSatheesh Paul 		rc = roc_npc_mcam_clear_counter(roc_npc, mcam->ctr_id);
12622d9d348SSatheesh Paul 		if (rc)
12722d9d348SSatheesh Paul 			return rc;
12822d9d348SSatheesh Paul 
12922d9d348SSatheesh Paul 		rc = roc_npc_mcam_free_counter(roc_npc, mcam->ctr_id);
13022d9d348SSatheesh Paul 		if (rc)
13122d9d348SSatheesh Paul 			return rc;
13222d9d348SSatheesh Paul 	}
13322d9d348SSatheesh Paul 
13422d9d348SSatheesh Paul 	return roc_npc_mcam_free_entry(roc_npc, mcam->mcam_id);
13522d9d348SSatheesh Paul }
13622d9d348SSatheesh Paul 
13722d9d348SSatheesh Paul int
13822d9d348SSatheesh Paul roc_npc_mcam_init(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
13922d9d348SSatheesh Paul 		  int mcam_id)
14022d9d348SSatheesh Paul {
14122d9d348SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
14222d9d348SSatheesh Paul 	int rc;
14322d9d348SSatheesh Paul 
14422d9d348SSatheesh Paul 	rc = npc_mcam_init(npc, flow, mcam_id);
14522d9d348SSatheesh Paul 	if (rc != 0) {
14622d9d348SSatheesh Paul 		plt_err("npc: mcam initialisation write failed");
14722d9d348SSatheesh Paul 		return rc;
14822d9d348SSatheesh Paul 	}
14922d9d348SSatheesh Paul 	return 0;
15022d9d348SSatheesh Paul }
15122d9d348SSatheesh Paul 
15222d9d348SSatheesh Paul int
15322d9d348SSatheesh Paul roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint16_t new_ent)
15422d9d348SSatheesh Paul {
15522d9d348SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
15622d9d348SSatheesh Paul 	struct mbox *mbox = npc->mbox;
15722d9d348SSatheesh Paul 	int rc;
15822d9d348SSatheesh Paul 
15922d9d348SSatheesh Paul 	rc = npc_mcam_move(mbox, old_ent, new_ent);
16022d9d348SSatheesh Paul 	if (rc)
16122d9d348SSatheesh Paul 		return rc;
16222d9d348SSatheesh Paul 
16322d9d348SSatheesh Paul 	return 0;
16422d9d348SSatheesh Paul }
16522d9d348SSatheesh Paul 
16622d9d348SSatheesh Paul int
167a07f7cedSKiran Kumar K roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc)
168a07f7cedSKiran Kumar K {
169a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
170a07f7cedSKiran Kumar K 
171a07f7cedSKiran Kumar K 	return npc_flow_free_all_resources(npc);
172a07f7cedSKiran Kumar K }
173a07f7cedSKiran Kumar K 
174a07f7cedSKiran Kumar K int
175df29c91cSHarman Kalra roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, int *alloc_entry, int req_count,
176df29c91cSHarman Kalra 			   int priority, int *resp_count, bool is_conti)
177a07f7cedSKiran Kumar K {
178a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
179a07f7cedSKiran Kumar K 
180df5cf15fSKiran Kumar K 	return npc_mcam_alloc_entries(npc->mbox, ref_entry, alloc_entry, req_count, priority,
181df29c91cSHarman Kalra 				      resp_count, is_conti);
182a07f7cedSKiran Kumar K }
183a07f7cedSKiran Kumar K 
184a07f7cedSKiran Kumar K int
185fbc0fa74SKiran Kumar K roc_npc_mcam_enable_all_entries(struct roc_npc *roc_npc, bool enable)
186fbc0fa74SKiran Kumar K {
187fbc0fa74SKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
188fbc0fa74SKiran Kumar K 
189fbc0fa74SKiran Kumar K 	return npc_flow_enable_all_entries(npc, enable);
190fbc0fa74SKiran Kumar K }
191fbc0fa74SKiran Kumar K 
192fbc0fa74SKiran Kumar K int
193a07f7cedSKiran Kumar K roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
194a07f7cedSKiran Kumar K 			 struct roc_npc_flow *ref_mcam, int prio,
195a07f7cedSKiran Kumar K 			 int *resp_count)
196a07f7cedSKiran Kumar K {
197a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
198a07f7cedSKiran Kumar K 
199a07f7cedSKiran Kumar K 	return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count);
200a07f7cedSKiran Kumar K }
201a07f7cedSKiran Kumar K 
202a07f7cedSKiran Kumar K int
203a07f7cedSKiran Kumar K roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam,
204a07f7cedSKiran Kumar K 			   bool enable)
205a07f7cedSKiran Kumar K {
206a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
207a07f7cedSKiran Kumar K 
208a07f7cedSKiran Kumar K 	return npc_mcam_ena_dis_entry(npc, mcam, enable);
209a07f7cedSKiran Kumar K }
210a07f7cedSKiran Kumar K 
211a07f7cedSKiran Kumar K int
212a07f7cedSKiran Kumar K roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam)
213a07f7cedSKiran Kumar K {
214a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
215a07f7cedSKiran Kumar K 
216df5cf15fSKiran Kumar K 	return npc_mcam_write_entry(npc->mbox, mcam);
217a07f7cedSKiran Kumar K }
218a07f7cedSKiran Kumar K 
219a07f7cedSKiran Kumar K int
220a07f7cedSKiran Kumar K roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
221a07f7cedSKiran Kumar K {
222a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
223a07f7cedSKiran Kumar K 
224a07f7cedSKiran Kumar K 	if (roc_model_is_cn10k())
225a07f7cedSKiran Kumar K 		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
2268b9f07b8SHarman Kalra 	else if (roc_model_is_cn98xx())
2278b9f07b8SHarman Kalra 		return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1);
228a07f7cedSKiran Kumar K 	else
229a07f7cedSKiran Kumar K 		return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1);
230a07f7cedSKiran Kumar K }
231a07f7cedSKiran Kumar K 
232a07f7cedSKiran Kumar K static int
233a07f7cedSKiran Kumar K npc_mcam_tot_entries(void)
234a07f7cedSKiran Kumar K {
235a07f7cedSKiran Kumar K 	/* FIXME: change to reading in AF from NPC_AF_CONST1/2
236a07f7cedSKiran Kumar K 	 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
237a07f7cedSKiran Kumar K 	 */
23819f3cc23SSatheesh Paul 	if (roc_model_is_cn10k() || roc_model_is_cn98xx())
239a07f7cedSKiran Kumar K 		return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
240a07f7cedSKiran Kumar K 	else
241a07f7cedSKiran Kumar K 		return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
242a07f7cedSKiran Kumar K }
243a07f7cedSKiran Kumar K 
244a07f7cedSKiran Kumar K const char *
245a07f7cedSKiran Kumar K roc_npc_profile_name_get(struct roc_npc *roc_npc)
246a07f7cedSKiran Kumar K {
247a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
248a07f7cedSKiran Kumar K 
249a07f7cedSKiran Kumar K 	return (char *)npc->profile_name;
250a07f7cedSKiran Kumar K }
251a07f7cedSKiran Kumar K 
252a07f7cedSKiran Kumar K int
2533c3accd0SSatheesh Paul roc_npc_kex_capa_get(struct roc_nix *roc_nix, uint64_t *kex_capability)
2543c3accd0SSatheesh Paul {
2553c3accd0SSatheesh Paul 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
2563c3accd0SSatheesh Paul 	struct npc npc;
2573c3accd0SSatheesh Paul 	int rc = 0;
2583c3accd0SSatheesh Paul 
2593c3accd0SSatheesh Paul 	memset(&npc, 0, sizeof(npc));
2603c3accd0SSatheesh Paul 
2613c3accd0SSatheesh Paul 	npc.mbox = (&nix->dev)->mbox;
2623c3accd0SSatheesh Paul 
2633c3accd0SSatheesh Paul 	rc = npc_mcam_fetch_kex_cfg(&npc);
2643c3accd0SSatheesh Paul 	if (rc)
2653c3accd0SSatheesh Paul 		return rc;
2663c3accd0SSatheesh Paul 
2673c3accd0SSatheesh Paul 	rc = npc_mcam_fetch_hw_cap(&npc, &npc.hash_extract_cap);
2683c3accd0SSatheesh Paul 	if (rc)
2693c3accd0SSatheesh Paul 		return rc;
2703c3accd0SSatheesh Paul 
2713c3accd0SSatheesh Paul 	*kex_capability = npc_get_kex_capability(&npc);
2723c3accd0SSatheesh Paul 
2733c3accd0SSatheesh Paul 	return 0;
2743c3accd0SSatheesh Paul }
2753c3accd0SSatheesh Paul 
2763c3accd0SSatheesh Paul int
277a07f7cedSKiran Kumar K roc_npc_init(struct roc_npc *roc_npc)
278a07f7cedSKiran Kumar K {
279a07f7cedSKiran Kumar K 	uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL;
280a07f7cedSKiran Kumar K 	struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
281a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
282a07f7cedSKiran Kumar K 	uint32_t bmap_sz;
283a07f7cedSKiran Kumar K 	int rc = 0, idx;
284a07f7cedSKiran Kumar K 	size_t sz;
285a07f7cedSKiran Kumar K 
286a07f7cedSKiran Kumar K 	PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ);
287a07f7cedSKiran Kumar K 
288a07f7cedSKiran Kumar K 	memset(npc, 0, sizeof(*npc));
289a07f7cedSKiran Kumar K 	npc->mbox = (&nix->dev)->mbox;
290a07f7cedSKiran Kumar K 	roc_npc->channel = nix->rx_chan_base;
291a07f7cedSKiran Kumar K 	roc_npc->pf_func = (&nix->dev)->pf_func;
292a07f7cedSKiran Kumar K 	npc->channel = roc_npc->channel;
293a07f7cedSKiran Kumar K 	npc->pf_func = roc_npc->pf_func;
294a07f7cedSKiran Kumar K 	npc->flow_max_priority = roc_npc->flow_max_priority;
295a07f7cedSKiran Kumar K 	npc->switch_header_type = roc_npc->switch_header_type;
296a07f7cedSKiran Kumar K 	npc->flow_prealloc_size = roc_npc->flow_prealloc_size;
297a07f7cedSKiran Kumar K 
298a07f7cedSKiran Kumar K 	if (npc->mbox == NULL)
299a07f7cedSKiran Kumar K 		return NPC_ERR_PARAM;
300a07f7cedSKiran Kumar K 
301a07f7cedSKiran Kumar K 	rc = npc_mcam_fetch_kex_cfg(npc);
302a07f7cedSKiran Kumar K 	if (rc)
303a07f7cedSKiran Kumar K 		goto done;
304a07f7cedSKiran Kumar K 
305e3315630SSatheesh Paul 	rc = npc_mcam_fetch_hw_cap(npc, &npc->hash_extract_cap);
306e3315630SSatheesh Paul 	if (rc)
307e3315630SSatheesh Paul 		goto done;
308e3315630SSatheesh Paul 
309a07f7cedSKiran Kumar K 	roc_npc->kex_capability = npc_get_kex_capability(npc);
310a07f7cedSKiran Kumar K 	roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX];
311a07f7cedSKiran Kumar K 
312a07f7cedSKiran Kumar K 	npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
313a9064972SNithin Dabilpuram 	nix->exact_match_ena = npc->exact_match_ena;
314a07f7cedSKiran Kumar K 
315a07f7cedSKiran Kumar K 	/* Free, free_rev, live and live_rev entries */
316a07f7cedSKiran Kumar K 	bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
317a07f7cedSKiran Kumar K 	mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0);
318a07f7cedSKiran Kumar K 	if (mem == NULL) {
319a07f7cedSKiran Kumar K 		plt_err("Bmap alloc failed");
320a07f7cedSKiran Kumar K 		rc = NPC_ERR_NO_MEM;
321a07f7cedSKiran Kumar K 		return rc;
322a07f7cedSKiran Kumar K 	}
323a07f7cedSKiran Kumar K 
324a07f7cedSKiran Kumar K 	sz = npc->flow_max_priority * sizeof(struct npc_flow_list);
325a07f7cedSKiran Kumar K 	npc->flow_list = plt_zmalloc(sz, 0);
326a07f7cedSKiran Kumar K 	if (npc->flow_list == NULL) {
327a07f7cedSKiran Kumar K 		plt_err("flow_list alloc failed");
328a07f7cedSKiran Kumar K 		rc = NPC_ERR_NO_MEM;
329a07f7cedSKiran Kumar K 		goto done;
330a07f7cedSKiran Kumar K 	}
331a07f7cedSKiran Kumar K 
3321f669198SSatheesh Paul 	sz = npc->flow_max_priority * sizeof(struct npc_prio_flow_list_head);
3331f669198SSatheesh Paul 	npc->prio_flow_list = plt_zmalloc(sz, 0);
3341f669198SSatheesh Paul 	if (npc->prio_flow_list == NULL) {
3351f669198SSatheesh Paul 		plt_err("prio_flow_list alloc failed");
3361f669198SSatheesh Paul 		rc = NPC_ERR_NO_MEM;
3371f669198SSatheesh Paul 		goto done;
3381f669198SSatheesh Paul 	}
3391f669198SSatheesh Paul 
340a07f7cedSKiran Kumar K 	npc_mem = mem;
341df5cf15fSKiran Kumar K 
342df5cf15fSKiran Kumar K 	TAILQ_INIT(&npc->ipsec_list);
343357f5ebcSAnkur Dwivedi 	TAILQ_INIT(&npc->age_flow_list);
344a07f7cedSKiran Kumar K 	for (idx = 0; idx < npc->flow_max_priority; idx++) {
345a07f7cedSKiran Kumar K 		TAILQ_INIT(&npc->flow_list[idx]);
3461f669198SSatheesh Paul 		TAILQ_INIT(&npc->prio_flow_list[idx]);
347a07f7cedSKiran Kumar K 	}
348a07f7cedSKiran Kumar K 
349a07f7cedSKiran Kumar K 	npc->rss_grps = NPC_RSS_GRPS;
350a07f7cedSKiran Kumar K 
351a07f7cedSKiran Kumar K 	bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps);
352a07f7cedSKiran Kumar K 	nix_mem = plt_zmalloc(bmap_sz, 0);
353a07f7cedSKiran Kumar K 	if (nix_mem == NULL) {
354a07f7cedSKiran Kumar K 		plt_err("Bmap alloc failed");
355a07f7cedSKiran Kumar K 		rc = NPC_ERR_NO_MEM;
356a07f7cedSKiran Kumar K 		goto done;
357a07f7cedSKiran Kumar K 	}
358a07f7cedSKiran Kumar K 
359a07f7cedSKiran Kumar K 	npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz);
360a07f7cedSKiran Kumar K 
361a07f7cedSKiran Kumar K 	if (!npc->rss_grp_entries) {
362a07f7cedSKiran Kumar K 		plt_err("bitmap init failed");
363a07f7cedSKiran Kumar K 		rc = NPC_ERR_NO_MEM;
364a07f7cedSKiran Kumar K 		goto done;
365a07f7cedSKiran Kumar K 	}
366a07f7cedSKiran Kumar K 
367a07f7cedSKiran Kumar K 	/* Group 0 will be used for RSS,
368a07f7cedSKiran Kumar K 	 * 1 -7 will be used for npc_flow RSS action
369a07f7cedSKiran Kumar K 	 */
370a07f7cedSKiran Kumar K 	plt_bitmap_set(npc->rss_grp_entries, 0);
371a07f7cedSKiran Kumar K 
3723ddc923bSAnkur Dwivedi 	roc_npc->flow_age.age_flow_refcnt = 0;
3733ddc923bSAnkur Dwivedi 
374a07f7cedSKiran Kumar K 	return rc;
375a07f7cedSKiran Kumar K 
376a07f7cedSKiran Kumar K done:
377a07f7cedSKiran Kumar K 	if (npc->flow_list)
378a07f7cedSKiran Kumar K 		plt_free(npc->flow_list);
3791f669198SSatheesh Paul 	if (npc->prio_flow_list)
3801f669198SSatheesh Paul 		plt_free(npc->prio_flow_list);
381a07f7cedSKiran Kumar K 	if (npc_mem)
382a07f7cedSKiran Kumar K 		plt_free(npc_mem);
383a07f7cedSKiran Kumar K 	return rc;
384a07f7cedSKiran Kumar K }
385a07f7cedSKiran Kumar K 
386a07f7cedSKiran Kumar K int
387a07f7cedSKiran Kumar K roc_npc_fini(struct roc_npc *roc_npc)
388a07f7cedSKiran Kumar K {
389a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
390a07f7cedSKiran Kumar K 	int rc;
391a07f7cedSKiran Kumar K 
392d1066ea6SHarman Kalra 	if (!roc_npc->flow_age.aged_flows_get_thread_exit)
39385e9542dSSatheesh Paul 		npc_aging_ctrl_thread_destroy(roc_npc);
39485e9542dSSatheesh Paul 
395a07f7cedSKiran Kumar K 	rc = npc_flow_free_all_resources(npc);
396a07f7cedSKiran Kumar K 	if (rc) {
397a07f7cedSKiran Kumar K 		plt_err("Error when deleting NPC MCAM entries, counters");
398a07f7cedSKiran Kumar K 		return rc;
399a07f7cedSKiran Kumar K 	}
400a07f7cedSKiran Kumar K 
401a07f7cedSKiran Kumar K 	if (npc->flow_list) {
402a07f7cedSKiran Kumar K 		plt_free(npc->flow_list);
403a07f7cedSKiran Kumar K 		npc->flow_list = NULL;
404a07f7cedSKiran Kumar K 	}
405a07f7cedSKiran Kumar K 
4061f669198SSatheesh Paul 	if (npc->prio_flow_list) {
4071f669198SSatheesh Paul 		plt_free(npc->prio_flow_list);
4081f669198SSatheesh Paul 		npc->prio_flow_list = NULL;
409a07f7cedSKiran Kumar K 	}
410a07f7cedSKiran Kumar K 
411a07f7cedSKiran Kumar K 	return 0;
412a07f7cedSKiran Kumar K }
413a07f7cedSKiran Kumar K 
41415f0b8a5SSatheesh Paul int
41515f0b8a5SSatheesh Paul roc_npc_validate_portid_action(struct roc_npc *roc_npc_src,
41615f0b8a5SSatheesh Paul 			       struct roc_npc *roc_npc_dst)
41715f0b8a5SSatheesh Paul {
41815f0b8a5SSatheesh Paul 	struct roc_nix *roc_nix_src = roc_npc_src->roc_nix;
41915f0b8a5SSatheesh Paul 	struct nix *nix_src = roc_nix_to_nix_priv(roc_nix_src);
42015f0b8a5SSatheesh Paul 	struct roc_nix *roc_nix_dst = roc_npc_dst->roc_nix;
42115f0b8a5SSatheesh Paul 	struct nix *nix_dst = roc_nix_to_nix_priv(roc_nix_dst);
42215f0b8a5SSatheesh Paul 
42315f0b8a5SSatheesh Paul 	if (roc_nix_is_pf(roc_npc_dst->roc_nix)) {
42415f0b8a5SSatheesh Paul 		plt_err("Output port should be VF");
42515f0b8a5SSatheesh Paul 		return -EINVAL;
42615f0b8a5SSatheesh Paul 	}
42715f0b8a5SSatheesh Paul 
42815f0b8a5SSatheesh Paul 	if (nix_dst->dev.vf >= nix_src->dev.maxvf) {
42915f0b8a5SSatheesh Paul 		plt_err("Invalid VF for output port");
43015f0b8a5SSatheesh Paul 		return -EINVAL;
43115f0b8a5SSatheesh Paul 	}
43215f0b8a5SSatheesh Paul 
43315f0b8a5SSatheesh Paul 	if (nix_src->dev.pf != nix_dst->dev.pf) {
43415f0b8a5SSatheesh Paul 		plt_err("Output port should be VF of ingress PF");
43515f0b8a5SSatheesh Paul 		return -EINVAL;
43615f0b8a5SSatheesh Paul 	}
43715f0b8a5SSatheesh Paul 	return 0;
43815f0b8a5SSatheesh Paul }
43915f0b8a5SSatheesh Paul 
440a07f7cedSKiran Kumar K static int
44104087b78SSatheesh Paul npc_parse_spi_to_sa_action(struct roc_npc *roc_npc, const struct roc_npc_action *act,
44204087b78SSatheesh Paul 			   struct roc_npc_flow *flow, uint8_t *has_spi_to_sa_action)
443bbe8d1f1SKiran Kumar K {
444bbe8d1f1SKiran Kumar K 	const struct roc_npc_sec_action *sec_action;
44504087b78SSatheesh Paul 	struct nix_spi_to_sa_add_req *req;
44604087b78SSatheesh Paul 	struct nix_spi_to_sa_add_rsp *rsp;
44704087b78SSatheesh Paul 	struct nix_inl_dev *inl_dev;
44804087b78SSatheesh Paul 	struct idev_cfg *idev;
449bbe8d1f1SKiran Kumar K 	union {
450bbe8d1f1SKiran Kumar K 		uint64_t reg;
451bbe8d1f1SKiran Kumar K 		union nix_rx_vtag_action_u act;
452bbe8d1f1SKiran Kumar K 	} vtag_act;
45304087b78SSatheesh Paul 	struct mbox *mbox;
45404087b78SSatheesh Paul 	int rc;
455bbe8d1f1SKiran Kumar K 
45604087b78SSatheesh Paul 	if (roc_npc->roc_nix->custom_sa_action == 0 || roc_model_is_cn9k() == 1 ||
45704087b78SSatheesh Paul 	    act->conf == NULL || flow->is_validate)
458bbe8d1f1SKiran Kumar K 		return 0;
459bbe8d1f1SKiran Kumar K 
46004087b78SSatheesh Paul 	*has_spi_to_sa_action = true;
461bbe8d1f1SKiran Kumar K 	sec_action = act->conf;
462bbe8d1f1SKiran Kumar K 
463bbe8d1f1SKiran Kumar K 	vtag_act.reg = 0;
464bbe8d1f1SKiran Kumar K 	vtag_act.act.sa_xor = sec_action->sa_xor;
465bbe8d1f1SKiran Kumar K 	vtag_act.act.sa_hi = sec_action->sa_hi;
466bbe8d1f1SKiran Kumar K 	vtag_act.act.sa_lo = sec_action->sa_lo;
467bbe8d1f1SKiran Kumar K 
46804087b78SSatheesh Paul 	idev = idev_get_cfg();
46904087b78SSatheesh Paul 	if (!idev)
47004087b78SSatheesh Paul 		return -1;
47104087b78SSatheesh Paul 
47204087b78SSatheesh Paul 	inl_dev = idev->nix_inl_dev;
47304087b78SSatheesh Paul 
474bbe8d1f1SKiran Kumar K 	switch (sec_action->alg) {
475bbe8d1f1SKiran Kumar K 	case ROC_NPC_SEC_ACTION_ALG0:
476bbe8d1f1SKiran Kumar K 		break;
477bbe8d1f1SKiran Kumar K 	case ROC_NPC_SEC_ACTION_ALG1:
478bbe8d1f1SKiran Kumar K 		vtag_act.act.vtag1_valid = false;
479bbe8d1f1SKiran Kumar K 		vtag_act.act.vtag1_lid = ROC_NPC_SEC_ACTION_ALG1;
480bbe8d1f1SKiran Kumar K 		break;
481bbe8d1f1SKiran Kumar K 	case ROC_NPC_SEC_ACTION_ALG2:
482bbe8d1f1SKiran Kumar K 		vtag_act.act.vtag1_valid = false;
483bbe8d1f1SKiran Kumar K 		vtag_act.act.vtag1_lid = ROC_NPC_SEC_ACTION_ALG2;
484bbe8d1f1SKiran Kumar K 		break;
48504087b78SSatheesh Paul 	case ROC_NPC_SEC_ACTION_ALG3:
48604087b78SSatheesh Paul 		vtag_act.act.vtag1_valid = false;
487bfc1fcceSKiran Kumar K 		vtag_act.act.vtag1_lid = ROC_NPC_SEC_ACTION_ALG3;
488bfc1fcceSKiran Kumar K 		break;
489bfc1fcceSKiran Kumar K 	case ROC_NPC_SEC_ACTION_ALG4:
490bfc1fcceSKiran Kumar K 		vtag_act.act.vtag1_valid = false;
49104087b78SSatheesh Paul 		vtag_act.act.vtag1_lid = 0;
49204087b78SSatheesh Paul 		mbox = inl_dev->dev.mbox;
49304087b78SSatheesh Paul 		req = mbox_alloc_msg_nix_spi_to_sa_add(mbox);
49404087b78SSatheesh Paul 		if (req == NULL)
49504087b78SSatheesh Paul 			return -ENOSPC;
49604087b78SSatheesh Paul 		req->sa_index = sec_action->sa_index;
49704087b78SSatheesh Paul 		req->spi_index = plt_be_to_cpu_32(flow->spi_to_sa_info.spi);
49804087b78SSatheesh Paul 		req->match_id = flow->match_id;
49904087b78SSatheesh Paul 		req->valid = true;
50004087b78SSatheesh Paul 		rc = mbox_process_msg(mbox, (void *)&rsp);
50104087b78SSatheesh Paul 		if (rc)
50204087b78SSatheesh Paul 			return rc;
50304087b78SSatheesh Paul 		flow->spi_to_sa_info.hash_index = rsp->hash_index;
50404087b78SSatheesh Paul 		flow->spi_to_sa_info.way = rsp->way;
50504087b78SSatheesh Paul 		flow->spi_to_sa_info.duplicate = rsp->is_duplicate;
50604087b78SSatheesh Paul 		flow->spi_to_sa_info.has_action = true;
50704087b78SSatheesh Paul 		break;
508bbe8d1f1SKiran Kumar K 	default:
509bbe8d1f1SKiran Kumar K 		return -1;
510bbe8d1f1SKiran Kumar K 	}
511bbe8d1f1SKiran Kumar K 
512bbe8d1f1SKiran Kumar K 	flow->vtag_action = vtag_act.reg;
513bbe8d1f1SKiran Kumar K 
514bbe8d1f1SKiran Kumar K 	return 0;
515bbe8d1f1SKiran Kumar K }
516bbe8d1f1SKiran Kumar K 
517bbe8d1f1SKiran Kumar K static int
518209188d1SSatheesh Paul roc_npc_process_sample_action(struct roc_npc *roc_npc,
519209188d1SSatheesh Paul 			      const struct roc_npc_action_sample *sample_action,
520209188d1SSatheesh Paul 			      struct roc_npc_flow *flow)
521209188d1SSatheesh Paul {
522209188d1SSatheesh Paul 	struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix);
523209188d1SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
524209188d1SSatheesh Paul 
525209188d1SSatheesh Paul 	flow->is_sampling_rule = true;
526209188d1SSatheesh Paul 
527209188d1SSatheesh Paul 	switch (sample_action->action_type) {
528209188d1SSatheesh Paul 	case ROC_NPC_ACTION_TYPE_PORT_ID:
529209188d1SSatheesh Paul 		flow->mcast_pf_funcs[0] = sample_action->pf_func;
530209188d1SSatheesh Paul 		flow->mcast_channels[0] = sample_action->channel;
531209188d1SSatheesh Paul 		break;
532209188d1SSatheesh Paul 	case ROC_NPC_ACTION_TYPE_PF:
533209188d1SSatheesh Paul 		flow->mcast_pf_funcs[0] = roc_npc->pf_func;
534209188d1SSatheesh Paul 		flow->mcast_channels[0] = npc->channel;
535209188d1SSatheesh Paul 		break;
536209188d1SSatheesh Paul 	case ROC_NPC_ACTION_TYPE_VF:
537209188d1SSatheesh Paul 		if (sample_action->pf_func >= nix->dev.maxvf)
538209188d1SSatheesh Paul 			return -EINVAL;
539209188d1SSatheesh Paul 		flow->mcast_pf_funcs[0] =
540209188d1SSatheesh Paul 			((roc_npc->pf_func & 0xfc00) | (sample_action->pf_func + 1));
541209188d1SSatheesh Paul 		flow->mcast_channels[0] = npc->channel;
542209188d1SSatheesh Paul 		break;
543209188d1SSatheesh Paul 	default:
544209188d1SSatheesh Paul 		return -EINVAL;
545209188d1SSatheesh Paul 	}
546209188d1SSatheesh Paul 
547209188d1SSatheesh Paul 	return 0;
548209188d1SSatheesh Paul }
549209188d1SSatheesh Paul 
550209188d1SSatheesh Paul static int
551ee48f711SNithin Dabilpuram npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
552b7eb0e0cSSatheesh Paul 		  const struct roc_npc_action actions[], struct roc_npc_flow *flow,
553b7eb0e0cSSatheesh Paul 		  uint16_t dst_pf_func)
554a07f7cedSKiran Kumar K {
555ee48f711SNithin Dabilpuram 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
55604087b78SSatheesh Paul 	const struct roc_npc_action *sec_action = NULL;
557209188d1SSatheesh Paul 	const struct roc_npc_action_sample *act_sample;
558a07f7cedSKiran Kumar K 	const struct roc_npc_action_mark *act_mark;
5590ca63f1bSSunil Kumar Kori 	const struct roc_npc_action_meter *act_mtr;
560a07f7cedSKiran Kumar K 	const struct roc_npc_action_queue *act_q;
561a07f7cedSKiran Kumar K 	const struct roc_npc_action_vf *vf_act;
56219f3cc23SSatheesh Paul 	bool vlan_insert_action = false;
56304087b78SSatheesh Paul 	uint8_t has_spi_to_sa_act = 0;
564a07f7cedSKiran Kumar K 	int sel_act, req_act = 0;
565a07f7cedSKiran Kumar K 	uint16_t pf_func, vf_id;
5663c100e0eSNithin Dabilpuram 	struct roc_nix *roc_nix;
567a07f7cedSKiran Kumar K 	int errcode = 0;
568a07f7cedSKiran Kumar K 	int mark = 0;
569a07f7cedSKiran Kumar K 	int rq = 0;
570bbe8d1f1SKiran Kumar K 	int rc = 0;
571a07f7cedSKiran Kumar K 
572a07f7cedSKiran Kumar K 	/* Initialize actions */
573a07f7cedSKiran Kumar K 	flow->ctr_id = NPC_COUNTER_NONE;
57467e1cbf3SRakesh Kudurumalla 	flow->mtr_id = ROC_NIX_MTR_ID_INVALID;
575a07f7cedSKiran Kumar K 	pf_func = npc->pf_func;
576296e9040SKiran Kumar K 	if (flow->has_rep)
577296e9040SKiran Kumar K 		pf_func = flow->rep_pf_func;
578a07f7cedSKiran Kumar K 
579a07f7cedSKiran Kumar K 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
580a07f7cedSKiran Kumar K 		switch (actions->type) {
581a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_VOID:
582a07f7cedSKiran Kumar K 			break;
583a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_MARK:
584a07f7cedSKiran Kumar K 			act_mark = (const struct roc_npc_action_mark *)
585a07f7cedSKiran Kumar K 					   actions->conf;
586a07f7cedSKiran Kumar K 			if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) {
587a07f7cedSKiran Kumar K 				plt_err("mark value must be < 0xfffe");
588a07f7cedSKiran Kumar K 				goto err_exit;
589a07f7cedSKiran Kumar K 			}
590a07f7cedSKiran Kumar K 			mark = act_mark->id + 1;
591a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_MARK;
5928a44b2a5SHanumanth Pothula 			npc->mark_actions += 1;
59304087b78SSatheesh Paul 			flow->match_id = mark;
594a07f7cedSKiran Kumar K 			break;
595a07f7cedSKiran Kumar K 
596a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_FLAG:
597a07f7cedSKiran Kumar K 			mark = NPC_FLOW_FLAG_VAL;
598a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_FLAG;
5998a44b2a5SHanumanth Pothula 			npc->mark_actions += 1;
600a07f7cedSKiran Kumar K 			break;
601a07f7cedSKiran Kumar K 
602a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_COUNT:
603a07f7cedSKiran Kumar K 			/* Indicates, need a counter */
60422d9d348SSatheesh Paul 			flow->use_ctr = 1;
605a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_COUNT;
606a07f7cedSKiran Kumar K 			break;
607a07f7cedSKiran Kumar K 
608a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_DROP:
609a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_DROP;
610a07f7cedSKiran Kumar K 			break;
611a07f7cedSKiran Kumar K 
612a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_PF:
613a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_PF;
614a07f7cedSKiran Kumar K 			pf_func &= (0xfc00);
615a07f7cedSKiran Kumar K 			break;
616a07f7cedSKiran Kumar K 
617a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_VF:
618209188d1SSatheesh Paul 			vf_act = (const struct roc_npc_action_vf *)actions->conf;
619a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_VF;
6207816df79SHarman Kalra 			if (roc_model_is_cn20k())
6217816df79SHarman Kalra 				vf_id = vf_act->id & RVU_PFVF_FUNC_MASK_CN20K;
6227816df79SHarman Kalra 			else
623a07f7cedSKiran Kumar K 				vf_id = vf_act->id & RVU_PFVF_FUNC_MASK;
624a07f7cedSKiran Kumar K 			pf_func &= (0xfc00);
625a07f7cedSKiran Kumar K 			pf_func = (pf_func | (vf_id + 1));
626a07f7cedSKiran Kumar K 			break;
627a07f7cedSKiran Kumar K 
62815f0b8a5SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_PORT_ID:
629b7eb0e0cSSatheesh Paul 			pf_func = dst_pf_func;
63015f0b8a5SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_VF;
63115f0b8a5SSatheesh Paul 			break;
63215f0b8a5SSatheesh Paul 
633a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_QUEUE:
634209188d1SSatheesh Paul 			act_q = (const struct roc_npc_action_queue *)actions->conf;
635209188d1SSatheesh Paul 			rq = act_q->index & 0xFFFFF;
636a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
637a07f7cedSKiran Kumar K 			break;
638a07f7cedSKiran Kumar K 
639a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_RSS:
640a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_RSS;
641a07f7cedSKiran Kumar K 			break;
642a07f7cedSKiran Kumar K 
643a07f7cedSKiran Kumar K 		case ROC_NPC_ACTION_TYPE_SEC:
644a07f7cedSKiran Kumar K 			/* Assumes user has already configured security
645a07f7cedSKiran Kumar K 			 * session for this flow. Associated conf is
646a07f7cedSKiran Kumar K 			 * opaque. When security is implemented,
647a07f7cedSKiran Kumar K 			 * we need to verify that for specified security
648a07f7cedSKiran Kumar K 			 * session:
649a07f7cedSKiran Kumar K 			 *  action_type ==
650a07f7cedSKiran Kumar K 			 *    NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL &&
651a07f7cedSKiran Kumar K 			 *  session_protocol ==
652a07f7cedSKiran Kumar K 			 *    NPC_SECURITY_PROTOCOL_IPSEC
653a07f7cedSKiran Kumar K 			 */
654a07f7cedSKiran Kumar K 			req_act |= ROC_NPC_ACTION_TYPE_SEC;
655a07f7cedSKiran Kumar K 			rq = 0;
6563c100e0eSNithin Dabilpuram 			roc_nix = roc_npc->roc_nix;
657ee48f711SNithin Dabilpuram 
658ee48f711SNithin Dabilpuram 			/* Special processing when with inline device */
6593c100e0eSNithin Dabilpuram 			if (roc_nix_inb_is_with_inl_dev(roc_nix) &&
660ee48f711SNithin Dabilpuram 			    roc_nix_inl_dev_is_probed()) {
6613c100e0eSNithin Dabilpuram 				struct roc_nix_rq *inl_rq;
6623c100e0eSNithin Dabilpuram 
6633c100e0eSNithin Dabilpuram 				inl_rq = roc_nix_inl_dev_rq(roc_nix);
6643c100e0eSNithin Dabilpuram 				if (!inl_rq) {
6653c100e0eSNithin Dabilpuram 					errcode = NPC_ERR_INTERNAL;
6663c100e0eSNithin Dabilpuram 					goto err_exit;
6673c100e0eSNithin Dabilpuram 				}
6683c100e0eSNithin Dabilpuram 				rq = inl_rq->qid;
669ee48f711SNithin Dabilpuram 				pf_func = nix_inl_dev_pffunc_get();
670ee48f711SNithin Dabilpuram 			}
6712c7ea812SSatheesh Paul 
6722c7ea812SSatheesh Paul 			if (roc_nix_inl_dev_is_probed())
6732c7ea812SSatheesh Paul 				flow->is_inline_dev = 1;
67404087b78SSatheesh Paul 			sec_action = actions;
675a07f7cedSKiran Kumar K 			break;
67619f3cc23SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_VLAN_STRIP:
67719f3cc23SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP;
67819f3cc23SSatheesh Paul 			break;
67919f3cc23SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_VLAN_INSERT:
68019f3cc23SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT;
68119f3cc23SSatheesh Paul 			break;
68219f3cc23SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT:
68319f3cc23SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
68419f3cc23SSatheesh Paul 			break;
68519f3cc23SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT:
68619f3cc23SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
68719f3cc23SSatheesh Paul 			break;
6880ca63f1bSSunil Kumar Kori 		case ROC_NPC_ACTION_TYPE_METER:
6890ca63f1bSSunil Kumar Kori 			act_mtr = (const struct roc_npc_action_meter *)
6900ca63f1bSSunil Kumar Kori 					  actions->conf;
6910ca63f1bSSunil Kumar Kori 			flow->mtr_id = act_mtr->mtr_id;
6920ca63f1bSSunil Kumar Kori 			req_act |= ROC_NPC_ACTION_TYPE_METER;
6930ca63f1bSSunil Kumar Kori 			break;
694357f5ebcSAnkur Dwivedi 		case ROC_NPC_ACTION_TYPE_AGE:
695357f5ebcSAnkur Dwivedi 			if (flow->is_validate == true)
696357f5ebcSAnkur Dwivedi 				break;
697357f5ebcSAnkur Dwivedi 			plt_seqcount_init(&roc_npc->flow_age.seq_cnt);
698357f5ebcSAnkur Dwivedi 			errcode = npc_aging_ctrl_thread_create(roc_npc,
699357f5ebcSAnkur Dwivedi 							       actions->conf,
700357f5ebcSAnkur Dwivedi 							       flow);
701357f5ebcSAnkur Dwivedi 			if (errcode != 0)
702357f5ebcSAnkur Dwivedi 				goto err_exit;
703357f5ebcSAnkur Dwivedi 			req_act |= ROC_NPC_ACTION_TYPE_AGE;
704357f5ebcSAnkur Dwivedi 			break;
705209188d1SSatheesh Paul 		case ROC_NPC_ACTION_TYPE_SAMPLE:
706209188d1SSatheesh Paul 			req_act |= ROC_NPC_ACTION_TYPE_SAMPLE;
707209188d1SSatheesh Paul 			act_sample = actions->conf;
708209188d1SSatheesh Paul 			errcode = roc_npc_process_sample_action(roc_npc, act_sample, flow);
709209188d1SSatheesh Paul 			if (errcode)
710209188d1SSatheesh Paul 				goto err_exit;
711209188d1SSatheesh Paul 			break;
712a07f7cedSKiran Kumar K 		default:
713a07f7cedSKiran Kumar K 			errcode = NPC_ERR_ACTION_NOTSUP;
714a07f7cedSKiran Kumar K 			goto err_exit;
715a07f7cedSKiran Kumar K 		}
716a07f7cedSKiran Kumar K 	}
717a07f7cedSKiran Kumar K 
71804087b78SSatheesh Paul 	if (sec_action) {
71904087b78SSatheesh Paul 		rc = npc_parse_spi_to_sa_action(roc_npc, sec_action, flow, &has_spi_to_sa_act);
72004087b78SSatheesh Paul 		if (rc) {
72104087b78SSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
72204087b78SSatheesh Paul 			goto err_exit;
72304087b78SSatheesh Paul 		}
72404087b78SSatheesh Paul 	}
72504087b78SSatheesh Paul 
72604087b78SSatheesh Paul 	if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
72719f3cc23SSatheesh Paul 		       ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT))
72819f3cc23SSatheesh Paul 		vlan_insert_action = true;
72919f3cc23SSatheesh Paul 
73004087b78SSatheesh Paul 	if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
73119f3cc23SSatheesh Paul 			ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) ==
73219f3cc23SSatheesh Paul 	    ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
73319f3cc23SSatheesh Paul 		plt_err("PCP insert action can't be supported alone");
734a07f7cedSKiran Kumar K 		errcode = NPC_ERR_ACTION_NOTSUP;
735a07f7cedSKiran Kumar K 		goto err_exit;
736a07f7cedSKiran Kumar K 	}
73719f3cc23SSatheesh Paul 
73804087b78SSatheesh Paul 	if (has_spi_to_sa_act && (vlan_insert_action ||
739bbe8d1f1SKiran Kumar K 			     (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP))) {
740bbe8d1f1SKiran Kumar K 		plt_err("Both MSNS and VLAN insert/strip action can't be supported"
741bbe8d1f1SKiran Kumar K 			" together");
742bbe8d1f1SKiran Kumar K 		errcode = NPC_ERR_ACTION_NOTSUP;
743bbe8d1f1SKiran Kumar K 		goto err_exit;
744bbe8d1f1SKiran Kumar K 	}
745bbe8d1f1SKiran Kumar K 
74619f3cc23SSatheesh Paul 	/* Both STRIP and INSERT actions are not supported */
74719f3cc23SSatheesh Paul 	if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) {
74819f3cc23SSatheesh Paul 		errcode = NPC_ERR_ACTION_NOTSUP;
74919f3cc23SSatheesh Paul 		goto err_exit;
75019f3cc23SSatheesh Paul 	}
75119f3cc23SSatheesh Paul 
752209188d1SSatheesh Paul 	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
753209188d1SSatheesh Paul 		/* One entry for the mce list PF and channel comes from the sample subaction.
754209188d1SSatheesh Paul 		 * Another one is the action target of the flow rule getting created.
755209188d1SSatheesh Paul 		 */
756209188d1SSatheesh Paul 		flow->mcast_pf_funcs[1] = pf_func;
757209188d1SSatheesh Paul 		flow->mcast_channels[1] = npc->channel;
758209188d1SSatheesh Paul 		if (req_act & (ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_SEC |
759209188d1SSatheesh Paul 			       ROC_NPC_ACTION_TYPE_RSS)) {
760209188d1SSatheesh Paul 			plt_err("Drop/RSS/SEC not supported with action type sample");
761209188d1SSatheesh Paul 			return -EINVAL;
762209188d1SSatheesh Paul 		}
763209188d1SSatheesh Paul 		if (flow->mcast_pf_funcs[0] == flow->mcast_pf_funcs[1]) {
764209188d1SSatheesh Paul 			plt_err("Sample destination and target cannot be same");
765209188d1SSatheesh Paul 			return -EINVAL;
766209188d1SSatheesh Paul 		}
767209188d1SSatheesh Paul 		if ((attr->egress) && (flow->mcast_channels[0] == flow->mcast_channels[1])) {
768209188d1SSatheesh Paul 			plt_err("Mirroring within PF and VF not allowed");
769209188d1SSatheesh Paul 			return -EINVAL;
770209188d1SSatheesh Paul 		}
771209188d1SSatheesh Paul 	}
772209188d1SSatheesh Paul 
77319f3cc23SSatheesh Paul 	/* Check if actions specified are compatible */
77419f3cc23SSatheesh Paul 	if (attr->egress) {
77519f3cc23SSatheesh Paul 		if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
77619f3cc23SSatheesh Paul 			plt_err("VLAN pop action is not supported on Egress");
77719f3cc23SSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
77819f3cc23SSatheesh Paul 			goto err_exit;
77919f3cc23SSatheesh Paul 		}
78019f3cc23SSatheesh Paul 
7818ca851cdSSatheesh Paul 		if (req_act &
782209188d1SSatheesh Paul 		    ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT |
783209188d1SSatheesh Paul 		      ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | ROC_NPC_ACTION_TYPE_DROP |
784209188d1SSatheesh Paul 		      ROC_NPC_ACTION_TYPE_COUNT | ROC_NPC_ACTION_TYPE_SAMPLE)) {
785209188d1SSatheesh Paul 			plt_err("Only VLAN insert, drop, count, sample supported on Egress");
7868ca851cdSSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
7878ca851cdSSatheesh Paul 			goto err_exit;
7888ca851cdSSatheesh Paul 		}
7898ca851cdSSatheesh Paul 
7908ca851cdSSatheesh Paul 		if (vlan_insert_action &&
7918ca851cdSSatheesh Paul 		    (req_act & ROC_NPC_ACTION_TYPE_DROP)) {
7928ca851cdSSatheesh Paul 			plt_err("Both VLAN insert and drop actions cannot be supported");
7938ca851cdSSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
7948ca851cdSSatheesh Paul 			goto err_exit;
7958ca851cdSSatheesh Paul 		}
7968ca851cdSSatheesh Paul 
79719f3cc23SSatheesh Paul 		if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
798a07f7cedSKiran Kumar K 			flow->npc_action = NIX_TX_ACTIONOP_DROP;
799296e9040SKiran Kumar K 		} else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) || vlan_insert_action) {
80019f3cc23SSatheesh Paul 			flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT;
801296e9040SKiran Kumar K 			if (flow->rep_act_rep) {
802296e9040SKiran Kumar K 				flow->npc_action = NIX_TX_ACTIONOP_UCAST_CHAN;
803296e9040SKiran Kumar K 				flow->npc_action |= (uint64_t)0x3f << 12;
804296e9040SKiran Kumar K 			}
80519f3cc23SSatheesh Paul 		} else {
80619f3cc23SSatheesh Paul 			plt_err("Unsupported action for egress");
80719f3cc23SSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
80819f3cc23SSatheesh Paul 			goto err_exit;
80919f3cc23SSatheesh Paul 		}
81019f3cc23SSatheesh Paul 
811209188d1SSatheesh Paul 		if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE) {
812209188d1SSatheesh Paul 			flow->mcast_pf_funcs[1] = pf_func;
813209188d1SSatheesh Paul 			flow->mcast_channels[1] = npc->channel;
814209188d1SSatheesh Paul 		}
815209188d1SSatheesh Paul 
816296e9040SKiran Kumar K 		/* PF func who is sending the packet */
817296e9040SKiran Kumar K 		flow->tx_pf_func = pf_func;
818296e9040SKiran Kumar K 		goto done;
81919f3cc23SSatheesh Paul 	} else {
82019f3cc23SSatheesh Paul 		if (vlan_insert_action) {
82119f3cc23SSatheesh Paul 			errcode = NPC_ERR_ACTION_NOTSUP;
82219f3cc23SSatheesh Paul 			goto err_exit;
82319f3cc23SSatheesh Paul 		}
824a07f7cedSKiran Kumar K 	}
825a07f7cedSKiran Kumar K 
826a07f7cedSKiran Kumar K 	/* We have already verified the attr, this is ingress.
827a07f7cedSKiran Kumar K 	 * - Exactly one terminating action is supported
828a07f7cedSKiran Kumar K 	 * - Exactly one of MARK or FLAG is supported
829a07f7cedSKiran Kumar K 	 * - If terminating action is DROP, only count is valid.
830a07f7cedSKiran Kumar K 	 */
831a07f7cedSKiran Kumar K 	sel_act = req_act & NPC_ACTION_TERM;
832a07f7cedSKiran Kumar K 	if ((sel_act & (sel_act - 1)) != 0) {
833a07f7cedSKiran Kumar K 		errcode = NPC_ERR_ACTION_NOTSUP;
834a07f7cedSKiran Kumar K 		goto err_exit;
835a07f7cedSKiran Kumar K 	}
836a07f7cedSKiran Kumar K 
837a07f7cedSKiran Kumar K 	if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
838a07f7cedSKiran Kumar K 		sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT;
839a07f7cedSKiran Kumar K 		if ((sel_act & (sel_act - 1)) != 0) {
840a07f7cedSKiran Kumar K 			errcode = NPC_ERR_ACTION_NOTSUP;
841a07f7cedSKiran Kumar K 			goto err_exit;
842a07f7cedSKiran Kumar K 		}
843a07f7cedSKiran Kumar K 	}
844a07f7cedSKiran Kumar K 
845a07f7cedSKiran Kumar K 	if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) ==
846a07f7cedSKiran Kumar K 	    (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
847a07f7cedSKiran Kumar K 		errcode = NPC_ERR_ACTION_NOTSUP;
848a07f7cedSKiran Kumar K 		goto err_exit;
849a07f7cedSKiran Kumar K 	}
850a07f7cedSKiran Kumar K 
85119f3cc23SSatheesh Paul 	if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)
8528ca851cdSSatheesh Paul 		npc->vtag_strip_actions++;
85319f3cc23SSatheesh Paul 
854a07f7cedSKiran Kumar K 	/* Set NIX_RX_ACTIONOP */
8558ca851cdSSatheesh Paul 	if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
8568ca851cdSSatheesh Paul 		/* Only VLAN action is provided */
8578ca851cdSSatheesh Paul 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
858b1f677d4SSatheesh Paul 	} else if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) {
859b1f677d4SSatheesh Paul 		/* Check if any other action is set */
860b1f677d4SSatheesh Paul 		if ((req_act == ROC_NPC_ACTION_TYPE_PF) || (req_act == ROC_NPC_ACTION_TYPE_VF)) {
861b1f677d4SSatheesh Paul 			flow->npc_action = NIX_RX_ACTIONOP_DEFAULT;
862b1f677d4SSatheesh Paul 		} else {
863a07f7cedSKiran Kumar K 			flow->npc_action = NIX_RX_ACTIONOP_UCAST;
864a07f7cedSKiran Kumar K 			if (req_act & ROC_NPC_ACTION_TYPE_QUEUE)
865209188d1SSatheesh Paul 				flow->recv_queue = rq;
866b1f677d4SSatheesh Paul 		}
867a07f7cedSKiran Kumar K 	} else if (req_act & ROC_NPC_ACTION_TYPE_DROP) {
868a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_DROP;
869a07f7cedSKiran Kumar K 	} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
870a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
871209188d1SSatheesh Paul 		flow->recv_queue = rq;
872a07f7cedSKiran Kumar K 	} else if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
873a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
874a07f7cedSKiran Kumar K 	} else if (req_act & ROC_NPC_ACTION_TYPE_SEC) {
875a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC;
876a07f7cedSKiran Kumar K 		flow->npc_action |= (uint64_t)rq << 20;
877b1f677d4SSatheesh Paul 	} else if (req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) {
878a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
879a07f7cedSKiran Kumar K 	} else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) {
880a07f7cedSKiran Kumar K 		/* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end
881a07f7cedSKiran Kumar K 		 * This is default action, when user specify only
882a07f7cedSKiran Kumar K 		 * COUNT ACTION
883a07f7cedSKiran Kumar K 		 */
884a07f7cedSKiran Kumar K 		flow->npc_action = NIX_RX_ACTIONOP_UCAST;
885a07f7cedSKiran Kumar K 	} else {
886a07f7cedSKiran Kumar K 		/* Should never reach here */
887a07f7cedSKiran Kumar K 		errcode = NPC_ERR_ACTION_NOTSUP;
888a07f7cedSKiran Kumar K 		goto err_exit;
889a07f7cedSKiran Kumar K 	}
890a07f7cedSKiran Kumar K 
891209188d1SSatheesh Paul 	if (req_act & ROC_NPC_ACTION_TYPE_SAMPLE)
892209188d1SSatheesh Paul 		flow->npc_action = NIX_RX_ACTIONOP_MCAST;
893209188d1SSatheesh Paul 
894a07f7cedSKiran Kumar K 	if (mark)
895a07f7cedSKiran Kumar K 		flow->npc_action |= (uint64_t)mark << 40;
896a07f7cedSKiran Kumar K 
897a07f7cedSKiran Kumar K 	/* Ideally AF must ensure that correct pf_func is set */
898a07f7cedSKiran Kumar K 	flow->npc_action |= (uint64_t)pf_func << 4;
899a07f7cedSKiran Kumar K 
900296e9040SKiran Kumar K done:
901a07f7cedSKiran Kumar K 	return 0;
902a07f7cedSKiran Kumar K 
903a07f7cedSKiran Kumar K err_exit:
904a07f7cedSKiran Kumar K 	return errcode;
905a07f7cedSKiran Kumar K }
906a07f7cedSKiran Kumar K 
907a07f7cedSKiran Kumar K typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst);
908a07f7cedSKiran Kumar K 
909a07f7cedSKiran Kumar K static int
910a07f7cedSKiran Kumar K npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[],
911a07f7cedSKiran Kumar K 		  struct roc_npc_flow *flow, struct npc_parse_state *pst)
912a07f7cedSKiran Kumar K {
913a07f7cedSKiran Kumar K 	npc_parse_stage_func_t parse_stage_funcs[] = {
914296e9040SKiran Kumar K 		npc_parse_meta_items, npc_parse_port_representor_id,
915296e9040SKiran Kumar K 		npc_parse_mark_item,  npc_parse_pre_l2,
916296e9040SKiran Kumar K 		npc_parse_cpt_hdr,    npc_parse_higig2_hdr,
917296e9040SKiran Kumar K 		npc_parse_tx_queue,   npc_parse_la,
918296e9040SKiran Kumar K 		npc_parse_lb,	      npc_parse_lc,
919296e9040SKiran Kumar K 		npc_parse_ld,	      npc_parse_le,
920296e9040SKiran Kumar K 		npc_parse_lf,	      npc_parse_lg,
921296e9040SKiran Kumar K 		npc_parse_lh,
922a07f7cedSKiran Kumar K 	};
923a07f7cedSKiran Kumar K 	uint8_t layer = 0;
924a07f7cedSKiran Kumar K 	int key_offset;
925a07f7cedSKiran Kumar K 	int rc;
926a07f7cedSKiran Kumar K 
927a07f7cedSKiran Kumar K 	if (pattern == NULL)
928a07f7cedSKiran Kumar K 		return NPC_ERR_PARAM;
929a07f7cedSKiran Kumar K 
930a07f7cedSKiran Kumar K 	pst->npc = npc;
931a07f7cedSKiran Kumar K 	pst->flow = flow;
932b7fff4e4SSatheesh Paul 	pst->nix_intf = flow->nix_intf;
933a07f7cedSKiran Kumar K 
934a07f7cedSKiran Kumar K 	/* Use integral byte offset */
935a07f7cedSKiran Kumar K 	key_offset = pst->npc->keyx_len[flow->nix_intf];
936a07f7cedSKiran Kumar K 	key_offset = (key_offset + 7) / 8;
937a07f7cedSKiran Kumar K 
938a07f7cedSKiran Kumar K 	/* Location where LDATA would begin */
939a07f7cedSKiran Kumar K 	pst->mcam_data = (uint8_t *)flow->mcam_data;
940a07f7cedSKiran Kumar K 	pst->mcam_mask = (uint8_t *)flow->mcam_mask;
941a07f7cedSKiran Kumar K 
942a07f7cedSKiran Kumar K 	while (pattern->type != ROC_NPC_ITEM_TYPE_END &&
943a07f7cedSKiran Kumar K 	       layer < PLT_DIM(parse_stage_funcs)) {
944a07f7cedSKiran Kumar K 		/* Skip place-holders */
945a07f7cedSKiran Kumar K 		pattern = npc_parse_skip_void_and_any_items(pattern);
946a07f7cedSKiran Kumar K 
947a07f7cedSKiran Kumar K 		pst->pattern = pattern;
948a07f7cedSKiran Kumar K 		rc = parse_stage_funcs[layer](pst);
949a07f7cedSKiran Kumar K 		if (rc != 0)
950a07f7cedSKiran Kumar K 			return rc;
951a07f7cedSKiran Kumar K 
952a07f7cedSKiran Kumar K 		layer++;
953a07f7cedSKiran Kumar K 
954a07f7cedSKiran Kumar K 		/*
955a07f7cedSKiran Kumar K 		 * Parse stage function sets pst->pattern to
956a07f7cedSKiran Kumar K 		 * 1 past the last item it consumed.
957a07f7cedSKiran Kumar K 		 */
958a07f7cedSKiran Kumar K 		pattern = pst->pattern;
959a07f7cedSKiran Kumar K 
960a07f7cedSKiran Kumar K 		if (pst->terminate)
961a07f7cedSKiran Kumar K 			break;
962a07f7cedSKiran Kumar K 	}
963a07f7cedSKiran Kumar K 
964a07f7cedSKiran Kumar K 	/* Skip trailing place-holders */
965a07f7cedSKiran Kumar K 	pattern = npc_parse_skip_void_and_any_items(pattern);
966a07f7cedSKiran Kumar K 
967a07f7cedSKiran Kumar K 	/* Are there more items than what we can handle? */
968a07f7cedSKiran Kumar K 	if (pattern->type != ROC_NPC_ITEM_TYPE_END)
969a07f7cedSKiran Kumar K 		return NPC_ERR_PATTERN_NOTSUP;
970a07f7cedSKiran Kumar K 
971a07f7cedSKiran Kumar K 	return 0;
972a07f7cedSKiran Kumar K }
973a07f7cedSKiran Kumar K 
974a07f7cedSKiran Kumar K static int
975a07f7cedSKiran Kumar K npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr,
976a07f7cedSKiran Kumar K 	       struct roc_npc_flow *flow)
977a07f7cedSKiran Kumar K {
978a07f7cedSKiran Kumar K 	if (attr == NULL)
979a07f7cedSKiran Kumar K 		return NPC_ERR_PARAM;
980a07f7cedSKiran Kumar K 	else if (attr->priority >= npc->flow_max_priority)
981a07f7cedSKiran Kumar K 		return NPC_ERR_PARAM;
982a07f7cedSKiran Kumar K 	else if ((!attr->egress && !attr->ingress) ||
983a07f7cedSKiran Kumar K 		 (attr->egress && attr->ingress))
984a07f7cedSKiran Kumar K 		return NPC_ERR_PARAM;
985a07f7cedSKiran Kumar K 
986a07f7cedSKiran Kumar K 	if (attr->ingress)
987a07f7cedSKiran Kumar K 		flow->nix_intf = ROC_NPC_INTF_RX;
988a07f7cedSKiran Kumar K 	else
989a07f7cedSKiran Kumar K 		flow->nix_intf = ROC_NPC_INTF_TX;
990a07f7cedSKiran Kumar K 
991a07f7cedSKiran Kumar K 	flow->priority = attr->priority;
992a07f7cedSKiran Kumar K 	return 0;
993a07f7cedSKiran Kumar K }
994a07f7cedSKiran Kumar K 
995a07f7cedSKiran Kumar K static int
996ee48f711SNithin Dabilpuram npc_parse_rule(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
997b7eb0e0cSSatheesh Paul 	       const struct roc_npc_item_info pattern[], const struct roc_npc_action actions[],
998b7eb0e0cSSatheesh Paul 	       struct roc_npc_flow *flow, struct npc_parse_state *pst)
999a07f7cedSKiran Kumar K {
1000ee48f711SNithin Dabilpuram 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1001b7fff4e4SSatheesh Paul 	struct roc_nix *roc_nix = roc_npc->roc_nix;
1002b7fff4e4SSatheesh Paul 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
1003a07f7cedSKiran Kumar K 	int err;
1004a07f7cedSKiran Kumar K 
1005b7fff4e4SSatheesh Paul 	pst->nb_tx_queues = nix->nb_tx_queues;
1006b7fff4e4SSatheesh Paul 
1007a07f7cedSKiran Kumar K 	/* Check attr */
1008a07f7cedSKiran Kumar K 	err = npc_parse_attr(npc, attr, flow);
1009a07f7cedSKiran Kumar K 	if (err)
1010a07f7cedSKiran Kumar K 		return err;
1011a07f7cedSKiran Kumar K 
1012a07f7cedSKiran Kumar K 	/* Check pattern */
1013a07f7cedSKiran Kumar K 	err = npc_parse_pattern(npc, pattern, flow, pst);
1014a07f7cedSKiran Kumar K 	if (err)
1015a07f7cedSKiran Kumar K 		return err;
1016a07f7cedSKiran Kumar K 
1017a07f7cedSKiran Kumar K 	/* Check action */
1018b7eb0e0cSSatheesh Paul 	err = npc_parse_actions(roc_npc, attr, actions, flow, pst->dst_pf_func);
1019a07f7cedSKiran Kumar K 	if (err)
1020a07f7cedSKiran Kumar K 		return err;
1021a07f7cedSKiran Kumar K 	return 0;
1022a07f7cedSKiran Kumar K }
1023a07f7cedSKiran Kumar K 
1024a07f7cedSKiran Kumar K int
1025a07f7cedSKiran Kumar K roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
1026a07f7cedSKiran Kumar K 		   const struct roc_npc_item_info pattern[],
1027a07f7cedSKiran Kumar K 		   const struct roc_npc_action actions[],
1028a07f7cedSKiran Kumar K 		   struct roc_npc_flow *flow)
1029a07f7cedSKiran Kumar K {
1030a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1031a07f7cedSKiran Kumar K 	struct npc_parse_state parse_state = {0};
1032a07f7cedSKiran Kumar K 	int rc;
1033a07f7cedSKiran Kumar K 
1034b7eb0e0cSSatheesh Paul 	rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, &parse_state);
1035a07f7cedSKiran Kumar K 	if (rc)
1036a07f7cedSKiran Kumar K 		return rc;
1037a07f7cedSKiran Kumar K 
1038a07f7cedSKiran Kumar K 	parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
1039a07f7cedSKiran Kumar K 
1040a07f7cedSKiran Kumar K 	return npc_program_mcam(npc, &parse_state, 0);
1041a07f7cedSKiran Kumar K }
1042a07f7cedSKiran Kumar K 
104351dc6a80SSatheesh Paul int
104451dc6a80SSatheesh Paul npc_rss_free_grp_get(struct npc *npc, uint32_t *pos)
104551dc6a80SSatheesh Paul {
104651dc6a80SSatheesh Paul 	struct plt_bitmap *bmap = npc->rss_grp_entries;
104751dc6a80SSatheesh Paul 
104851dc6a80SSatheesh Paul 	for (*pos = 0; *pos < ROC_NIX_RSS_GRPS; ++*pos) {
104951dc6a80SSatheesh Paul 		if (!plt_bitmap_get(bmap, *pos))
105051dc6a80SSatheesh Paul 			break;
105151dc6a80SSatheesh Paul 	}
105251dc6a80SSatheesh Paul 	return *pos < ROC_NIX_RSS_GRPS ? 0 : -1;
105351dc6a80SSatheesh Paul }
105451dc6a80SSatheesh Paul 
105551dc6a80SSatheesh Paul int
1056*29a8df5cSHarman Kalra npc_rss_action_configure(struct roc_npc *roc_npc, const struct roc_npc_action_rss *rss,
1057*29a8df5cSHarman Kalra 			 uint8_t *alg_idx, uint32_t *rss_grp, uint32_t mcam_id,
1058*29a8df5cSHarman Kalra 			 uint16_t rss_repte_pf_func)
105951dc6a80SSatheesh Paul {
106051dc6a80SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
106151dc6a80SSatheesh Paul 	struct roc_nix *roc_nix = roc_npc->roc_nix;
106251dc6a80SSatheesh Paul 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
106351dc6a80SSatheesh Paul 	uint32_t flowkey_cfg, rss_grp_idx, i, rem;
106451dc6a80SSatheesh Paul 	uint8_t key[ROC_NIX_RSS_KEY_LEN];
106551dc6a80SSatheesh Paul 	const uint8_t *key_ptr;
106651dc6a80SSatheesh Paul 	uint8_t flowkey_algx;
106756fa6f92SKiran Kumar K 	uint32_t key_len;
106851dc6a80SSatheesh Paul 	uint16_t *reta;
106951dc6a80SSatheesh Paul 	int rc;
107051dc6a80SSatheesh Paul 
107156fa6f92SKiran Kumar K 	roc_nix_rss_key_get(roc_nix, key);
107256fa6f92SKiran Kumar K 	if (rss->key == NULL) {
107356fa6f92SKiran Kumar K 		key_ptr = key;
107456fa6f92SKiran Kumar K 	} else {
107556fa6f92SKiran Kumar K 		key_len = rss->key_len;
107656fa6f92SKiran Kumar K 		if (key_len > ROC_NIX_RSS_KEY_LEN)
107756fa6f92SKiran Kumar K 			key_len = ROC_NIX_RSS_KEY_LEN;
107856fa6f92SKiran Kumar K 
107956fa6f92SKiran Kumar K 		for (i = 0; i < key_len; i++) {
108056fa6f92SKiran Kumar K 			if (key[i] != rss->key[i]) {
108156fa6f92SKiran Kumar K 				plt_err("RSS key config not supported");
108256fa6f92SKiran Kumar K 				plt_err("New Key:");
108356fa6f92SKiran Kumar K 				for (i = 0; i < key_len; i++)
108456fa6f92SKiran Kumar K 					plt_dump_no_nl("0x%.2x ", rss->key[i]);
108556fa6f92SKiran Kumar K 				plt_dump_no_nl("\n");
108656fa6f92SKiran Kumar K 				plt_err("Configured Key:");
108756fa6f92SKiran Kumar K 				for (i = 0; i < ROC_NIX_RSS_KEY_LEN; i++)
108856fa6f92SKiran Kumar K 					plt_dump_no_nl("0x%.2x ", key[i]);
108956fa6f92SKiran Kumar K 				plt_dump_no_nl("\n");
109056fa6f92SKiran Kumar K 				return -ENOTSUP;
109156fa6f92SKiran Kumar K 			}
109256fa6f92SKiran Kumar K 		}
109356fa6f92SKiran Kumar K 		key_ptr = rss->key;
109456fa6f92SKiran Kumar K 	}
109556fa6f92SKiran Kumar K 
109651dc6a80SSatheesh Paul 	rc = npc_rss_free_grp_get(npc, &rss_grp_idx);
109751dc6a80SSatheesh Paul 	/* RSS group :0 is not usable for flow rss action */
109851dc6a80SSatheesh Paul 	if (rc < 0 || rss_grp_idx == 0)
109951dc6a80SSatheesh Paul 		return -ENOSPC;
110051dc6a80SSatheesh Paul 
1101*29a8df5cSHarman Kalra 	for (i = 0; (i < rss->queue_num) && !rss_repte_pf_func; i++) {
110251dc6a80SSatheesh Paul 		if (rss->queue[i] >= nix->nb_rx_queues) {
110351dc6a80SSatheesh Paul 			plt_err("queue id > max number of queues");
110451dc6a80SSatheesh Paul 			return -EINVAL;
110551dc6a80SSatheesh Paul 		}
110651dc6a80SSatheesh Paul 	}
110751dc6a80SSatheesh Paul 
110851dc6a80SSatheesh Paul 	*rss_grp = rss_grp_idx;
110951dc6a80SSatheesh Paul 
111051dc6a80SSatheesh Paul 	roc_nix_rss_key_set(roc_nix, key_ptr);
111151dc6a80SSatheesh Paul 
111251dc6a80SSatheesh Paul 	/* If queue count passed in the rss action is less than
111351dc6a80SSatheesh Paul 	 * HW configured reta size, replicate rss action reta
111451dc6a80SSatheesh Paul 	 * across HW reta table.
111551dc6a80SSatheesh Paul 	 */
111651dc6a80SSatheesh Paul 	reta = nix->reta[rss_grp_idx];
111751dc6a80SSatheesh Paul 
111851dc6a80SSatheesh Paul 	if (rss->queue_num > nix->reta_sz) {
111951dc6a80SSatheesh Paul 		plt_err("too many queues for RSS context");
112051dc6a80SSatheesh Paul 		return -ENOTSUP;
112151dc6a80SSatheesh Paul 	}
112251dc6a80SSatheesh Paul 
112351dc6a80SSatheesh Paul 	for (i = 0; i < (nix->reta_sz / rss->queue_num); i++)
112451dc6a80SSatheesh Paul 		memcpy(reta + i * rss->queue_num, rss->queue,
112551dc6a80SSatheesh Paul 		       sizeof(uint16_t) * rss->queue_num);
112651dc6a80SSatheesh Paul 
112751dc6a80SSatheesh Paul 	rem = nix->reta_sz % rss->queue_num;
112851dc6a80SSatheesh Paul 	if (rem)
1129*29a8df5cSHarman Kalra 		memcpy(&reta[i * rss->queue_num], rss->queue, rem * sizeof(uint16_t));
113051dc6a80SSatheesh Paul 
1131*29a8df5cSHarman Kalra 	rc = nix_rss_reta_pffunc_set(roc_nix, *rss_grp, reta, rss_repte_pf_func);
113251dc6a80SSatheesh Paul 	if (rc) {
113351dc6a80SSatheesh Paul 		plt_err("Failed to init rss table rc = %d", rc);
113451dc6a80SSatheesh Paul 		return rc;
113551dc6a80SSatheesh Paul 	}
113651dc6a80SSatheesh Paul 
113751dc6a80SSatheesh Paul 	flowkey_cfg = roc_npc->flowkey_cfg_state;
113851dc6a80SSatheesh Paul 
1139*29a8df5cSHarman Kalra 	rc = nix_rss_flowkey_pffunc_set(roc_nix, &flowkey_algx, flowkey_cfg, *rss_grp, mcam_id,
1140*29a8df5cSHarman Kalra 					rss_repte_pf_func);
114151dc6a80SSatheesh Paul 	if (rc) {
114251dc6a80SSatheesh Paul 		plt_err("Failed to set rss hash function rc = %d", rc);
114351dc6a80SSatheesh Paul 		return rc;
114451dc6a80SSatheesh Paul 	}
114551dc6a80SSatheesh Paul 
114651dc6a80SSatheesh Paul 	*alg_idx = flowkey_algx;
114751dc6a80SSatheesh Paul 
114851dc6a80SSatheesh Paul 	plt_bitmap_set(npc->rss_grp_entries, *rss_grp);
114951dc6a80SSatheesh Paul 
115051dc6a80SSatheesh Paul 	return 0;
115151dc6a80SSatheesh Paul }
115251dc6a80SSatheesh Paul 
115351dc6a80SSatheesh Paul int
115451dc6a80SSatheesh Paul npc_rss_action_program(struct roc_npc *roc_npc,
115551dc6a80SSatheesh Paul 		       const struct roc_npc_action actions[],
115651dc6a80SSatheesh Paul 		       struct roc_npc_flow *flow)
115751dc6a80SSatheesh Paul {
115851dc6a80SSatheesh Paul 	const struct roc_npc_action_rss *rss;
1159296e9040SKiran Kumar K 	struct roc_npc *npc = roc_npc;
116051dc6a80SSatheesh Paul 	uint32_t rss_grp;
116151dc6a80SSatheesh Paul 	uint8_t alg_idx;
116251dc6a80SSatheesh Paul 	int rc;
116351dc6a80SSatheesh Paul 
1164296e9040SKiran Kumar K 	if (flow->has_rep) {
1165296e9040SKiran Kumar K 		npc = roc_npc->rep_npc;
1166296e9040SKiran Kumar K 		npc->flowkey_cfg_state = roc_npc->flowkey_cfg_state;
1167296e9040SKiran Kumar K 	}
1168296e9040SKiran Kumar K 
116951dc6a80SSatheesh Paul 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
117051dc6a80SSatheesh Paul 		if (actions->type == ROC_NPC_ACTION_TYPE_RSS) {
117151dc6a80SSatheesh Paul 			rss = (const struct roc_npc_action_rss *)actions->conf;
1172*29a8df5cSHarman Kalra 			rc = npc_rss_action_configure(npc, rss, &alg_idx, &rss_grp, flow->mcam_id,
1173*29a8df5cSHarman Kalra 						      actions->rss_repte_pf_func);
117451dc6a80SSatheesh Paul 			if (rc)
117551dc6a80SSatheesh Paul 				return rc;
117651dc6a80SSatheesh Paul 
117751dc6a80SSatheesh Paul 			flow->npc_action &= (~(0xfULL));
117851dc6a80SSatheesh Paul 			flow->npc_action |= NIX_RX_ACTIONOP_RSS;
117951dc6a80SSatheesh Paul 			flow->npc_action |=
118051dc6a80SSatheesh Paul 				((uint64_t)(alg_idx & NPC_RSS_ACT_ALG_MASK)
118151dc6a80SSatheesh Paul 				 << NPC_RSS_ACT_ALG_OFFSET) |
118251dc6a80SSatheesh Paul 				((uint64_t)(rss_grp & NPC_RSS_ACT_GRP_MASK)
118351dc6a80SSatheesh Paul 				 << NPC_RSS_ACT_GRP_OFFSET);
118451dc6a80SSatheesh Paul 			break;
118551dc6a80SSatheesh Paul 		}
118651dc6a80SSatheesh Paul 	}
118751dc6a80SSatheesh Paul 	return 0;
118851dc6a80SSatheesh Paul }
118951dc6a80SSatheesh Paul 
119019f3cc23SSatheesh Paul static int
119119f3cc23SSatheesh Paul npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
119219f3cc23SSatheesh Paul {
119319f3cc23SSatheesh Paul 	struct roc_nix *roc_nix = roc_npc->roc_nix;
119419f3cc23SSatheesh Paul 	struct nix_vtag_config *vtag_cfg;
119519f3cc23SSatheesh Paul 	struct nix_vtag_config_rsp *rsp;
1196296e9040SKiran Kumar K 	struct mbox *mbox, *ombox;
119719f3cc23SSatheesh Paul 	struct nix *nix;
119819f3cc23SSatheesh Paul 	int rc = 0;
119919f3cc23SSatheesh Paul 
120019f3cc23SSatheesh Paul 	union {
120119f3cc23SSatheesh Paul 		uint64_t reg;
120219f3cc23SSatheesh Paul 		struct nix_tx_vtag_action_s act;
120319f3cc23SSatheesh Paul 	} tx_vtag_action;
120419f3cc23SSatheesh Paul 
120519f3cc23SSatheesh Paul 	nix = roc_nix_to_nix_priv(roc_nix);
1206296e9040SKiran Kumar K 	ombox = (&nix->dev)->mbox;
1207296e9040SKiran Kumar K 	if (flow->has_rep)
1208296e9040SKiran Kumar K 		ombox = flow->rep_mbox;
1209296e9040SKiran Kumar K 	mbox = mbox_get(ombox);
121019f3cc23SSatheesh Paul 
121119f3cc23SSatheesh Paul 	tx_vtag_action.reg = flow->vtag_action;
121219f3cc23SSatheesh Paul 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox);
121319f3cc23SSatheesh Paul 
121444a9307cSRakesh Kudurumalla 	if (vtag_cfg == NULL) {
121544a9307cSRakesh Kudurumalla 		rc = -ENOSPC;
121644a9307cSRakesh Kudurumalla 		goto exit;
121744a9307cSRakesh Kudurumalla 	}
121819f3cc23SSatheesh Paul 
121919f3cc23SSatheesh Paul 	vtag_cfg->cfg_type = VTAG_TX;
122019f3cc23SSatheesh Paul 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
122119f3cc23SSatheesh Paul 	vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def;
122219f3cc23SSatheesh Paul 	vtag_cfg->tx.free_vtag0 = true;
122319f3cc23SSatheesh Paul 
12248ca851cdSSatheesh Paul 	if (flow->vtag_insert_count == 2) {
12258ca851cdSSatheesh Paul 		vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def;
12268ca851cdSSatheesh Paul 		vtag_cfg->tx.free_vtag1 = true;
12278ca851cdSSatheesh Paul 	}
12288ca851cdSSatheesh Paul 
122919f3cc23SSatheesh Paul 	rc = mbox_process_msg(mbox, (void *)&rsp);
123019f3cc23SSatheesh Paul 	if (rc)
123144a9307cSRakesh Kudurumalla 		goto exit;
123219f3cc23SSatheesh Paul 
123344a9307cSRakesh Kudurumalla 	rc =  0;
123444a9307cSRakesh Kudurumalla exit:
123544a9307cSRakesh Kudurumalla 	mbox_put(mbox);
123644a9307cSRakesh Kudurumalla 	return rc;
123719f3cc23SSatheesh Paul }
123819f3cc23SSatheesh Paul 
123919f3cc23SSatheesh Paul static int
12408ca851cdSSatheesh Paul npc_vtag_insert_action_parse(const struct roc_npc_action actions[],
12418ca851cdSSatheesh Paul 			     struct roc_npc_flow *flow,
12428ca851cdSSatheesh Paul 			     struct npc_action_vtag_info *vlan_info,
12438ca851cdSSatheesh Paul 			     int *parsed_cnt)
124419f3cc23SSatheesh Paul {
12458ca851cdSSatheesh Paul 	bool vlan_id_found = false, ethtype_found = false, pcp_found = false;
12468ca851cdSSatheesh Paul 	int count = 0;
12478ca851cdSSatheesh Paul 
12488ca851cdSSatheesh Paul 	*parsed_cnt = 0;
12498ca851cdSSatheesh Paul 
12508ca851cdSSatheesh Paul 	/* This function parses parameters of one VLAN. When a parameter is
12518ca851cdSSatheesh Paul 	 * found repeated, it treats it as the end of first VLAN's parameters
12528ca851cdSSatheesh Paul 	 * and returns. The caller calls again to parse the parameters of the
12538ca851cdSSatheesh Paul 	 * second VLAN.
12548ca851cdSSatheesh Paul 	 */
12558ca851cdSSatheesh Paul 
12568ca851cdSSatheesh Paul 	for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) {
12578ca851cdSSatheesh Paul 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) {
12588ca851cdSSatheesh Paul 			if (vlan_id_found)
12598ca851cdSSatheesh Paul 				return 0;
12608ca851cdSSatheesh Paul 
12618ca851cdSSatheesh Paul 			const struct roc_npc_action_of_set_vlan_vid *vtag =
12628ca851cdSSatheesh Paul 				(const struct roc_npc_action_of_set_vlan_vid *)
12638ca851cdSSatheesh Paul 					actions->conf;
12648ca851cdSSatheesh Paul 
12658ca851cdSSatheesh Paul 			vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid);
12668ca851cdSSatheesh Paul 
12678ca851cdSSatheesh Paul 			if (vlan_info->vlan_id > 0xfff) {
12688ca851cdSSatheesh Paul 				plt_err("Invalid vlan_id for set vlan action");
12698ca851cdSSatheesh Paul 				return -EINVAL;
12708ca851cdSSatheesh Paul 			}
12718ca851cdSSatheesh Paul 
12728ca851cdSSatheesh Paul 			flow->vtag_insert_enabled = true;
12738ca851cdSSatheesh Paul 			(*parsed_cnt)++;
12748ca851cdSSatheesh Paul 			vlan_id_found = true;
12758ca851cdSSatheesh Paul 		} else if (actions->type ==
12768ca851cdSSatheesh Paul 			   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) {
12778ca851cdSSatheesh Paul 			if (ethtype_found)
12788ca851cdSSatheesh Paul 				return 0;
12798ca851cdSSatheesh Paul 
12808ca851cdSSatheesh Paul 			const struct roc_npc_action_of_push_vlan *ethtype =
12818ca851cdSSatheesh Paul 				(const struct roc_npc_action_of_push_vlan *)
12828ca851cdSSatheesh Paul 					actions->conf;
12838ca851cdSSatheesh Paul 			vlan_info->vlan_ethtype =
12848ca851cdSSatheesh Paul 				plt_be_to_cpu_16(ethtype->ethertype);
12858ca851cdSSatheesh Paul 			if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN &&
12868ca851cdSSatheesh Paul 			    vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) {
12878ca851cdSSatheesh Paul 				plt_err("Invalid ethtype specified for push"
12888ca851cdSSatheesh Paul 					" vlan action");
12898ca851cdSSatheesh Paul 				return -EINVAL;
12908ca851cdSSatheesh Paul 			}
12918ca851cdSSatheesh Paul 			flow->vtag_insert_enabled = true;
12928ca851cdSSatheesh Paul 			(*parsed_cnt)++;
12938ca851cdSSatheesh Paul 			ethtype_found = true;
12948ca851cdSSatheesh Paul 		} else if (actions->type ==
12958ca851cdSSatheesh Paul 			   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
12968ca851cdSSatheesh Paul 			if (pcp_found)
12978ca851cdSSatheesh Paul 				return 0;
12988ca851cdSSatheesh Paul 			const struct roc_npc_action_of_set_vlan_pcp *pcp =
12998ca851cdSSatheesh Paul 				(const struct roc_npc_action_of_set_vlan_pcp *)
13008ca851cdSSatheesh Paul 					actions->conf;
13018ca851cdSSatheesh Paul 			vlan_info->vlan_pcp = pcp->vlan_pcp;
13028ca851cdSSatheesh Paul 			if (vlan_info->vlan_pcp > 0x7) {
13038ca851cdSSatheesh Paul 				plt_err("Invalid PCP value for pcp action");
13048ca851cdSSatheesh Paul 				return -EINVAL;
13058ca851cdSSatheesh Paul 			}
13068ca851cdSSatheesh Paul 			flow->vtag_insert_enabled = true;
13078ca851cdSSatheesh Paul 			(*parsed_cnt)++;
13088ca851cdSSatheesh Paul 			pcp_found = true;
13098ca851cdSSatheesh Paul 		} else {
13108ca851cdSSatheesh Paul 			return 0;
13118ca851cdSSatheesh Paul 		}
13128ca851cdSSatheesh Paul 	}
13138ca851cdSSatheesh Paul 
13148ca851cdSSatheesh Paul 	return 0;
13158ca851cdSSatheesh Paul }
13168ca851cdSSatheesh Paul 
13178ca851cdSSatheesh Paul static int
13188ca851cdSSatheesh Paul npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow,
13198ca851cdSSatheesh Paul 				 struct npc_action_vtag_info *vlan_info)
13208ca851cdSSatheesh Paul {
132119f3cc23SSatheesh Paul 	struct nix_vtag_config *vtag_cfg;
132219f3cc23SSatheesh Paul 	struct nix_vtag_config_rsp *rsp;
13238ca851cdSSatheesh Paul 	int rc = 0;
132419f3cc23SSatheesh Paul 
132519f3cc23SSatheesh Paul 	union {
132619f3cc23SSatheesh Paul 		uint64_t reg;
132719f3cc23SSatheesh Paul 		struct nix_tx_vtag_action_s act;
132819f3cc23SSatheesh Paul 	} tx_vtag_action;
132919f3cc23SSatheesh Paul 
133044a9307cSRakesh Kudurumalla 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox_get(mbox));
133119f3cc23SSatheesh Paul 
133244a9307cSRakesh Kudurumalla 	if (vtag_cfg == NULL) {
133344a9307cSRakesh Kudurumalla 		rc = -ENOSPC;
133444a9307cSRakesh Kudurumalla 		goto exit;
133544a9307cSRakesh Kudurumalla 	}
133619f3cc23SSatheesh Paul 
13378ca851cdSSatheesh Paul 	vtag_cfg->cfg_type = VTAG_TX;
13388ca851cdSSatheesh Paul 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
13398ca851cdSSatheesh Paul 	vtag_cfg->tx.vtag0 =
13402447b0b6SGowrishankar Muthukrishnan 		(((uint32_t)vlan_info[0].vlan_ethtype << 16) |
13418ca851cdSSatheesh Paul 		 (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id);
13428ca851cdSSatheesh Paul 
13438ca851cdSSatheesh Paul 	vtag_cfg->tx.cfg_vtag0 = 1;
13448ca851cdSSatheesh Paul 
13458ca851cdSSatheesh Paul 	if (flow->vtag_insert_count == 2) {
13468ca851cdSSatheesh Paul 		vtag_cfg->tx.vtag1 =
13472447b0b6SGowrishankar Muthukrishnan 			(((uint32_t)vlan_info[1].vlan_ethtype << 16) |
13488ca851cdSSatheesh Paul 			 (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id);
13498ca851cdSSatheesh Paul 
13508ca851cdSSatheesh Paul 		vtag_cfg->tx.cfg_vtag1 = 1;
13518ca851cdSSatheesh Paul 	}
13528ca851cdSSatheesh Paul 
13538ca851cdSSatheesh Paul 	rc = mbox_process_msg(mbox, (void *)&rsp);
13548ca851cdSSatheesh Paul 	if (rc)
135544a9307cSRakesh Kudurumalla 		goto exit;
13568ca851cdSSatheesh Paul 
13578ca851cdSSatheesh Paul 	if (rsp->vtag0_idx < 0 ||
13588ca851cdSSatheesh Paul 	    ((flow->vtag_insert_count == 2) && (rsp->vtag1_idx < 0))) {
13598ca851cdSSatheesh Paul 		plt_err("Failed to config TX VTAG action");
136044a9307cSRakesh Kudurumalla 		rc =  -EINVAL;
136144a9307cSRakesh Kudurumalla 		goto exit;
13628ca851cdSSatheesh Paul 	}
13638ca851cdSSatheesh Paul 
13648ca851cdSSatheesh Paul 	tx_vtag_action.reg = 0;
13658ca851cdSSatheesh Paul 	tx_vtag_action.act.vtag0_def = rsp->vtag0_idx;
13668ca851cdSSatheesh Paul 	tx_vtag_action.act.vtag0_lid = NPC_LID_LA;
13678ca851cdSSatheesh Paul 	tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT;
13688ca851cdSSatheesh Paul 	tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR;
13698ca851cdSSatheesh Paul 
13708ca851cdSSatheesh Paul 	if (flow->vtag_insert_count == 2) {
13718ca851cdSSatheesh Paul 		tx_vtag_action.act.vtag1_def = rsp->vtag1_idx;
13728ca851cdSSatheesh Paul 		tx_vtag_action.act.vtag1_lid = NPC_LID_LA;
13738ca851cdSSatheesh Paul 		tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT;
13748ca851cdSSatheesh Paul 		/* NIX_TX_VTAG_ACTION_S
13758ca851cdSSatheesh Paul 		 *  If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte
13768ca851cdSSatheesh Paul 		 *  offset accordingly. Thus, if the two offsets are equal in
13778ca851cdSSatheesh Paul 		 *  the structure, hardware inserts Vtag 1 immediately after
13788ca851cdSSatheesh Paul 		 *  Vtag 0 in the packet.
13798ca851cdSSatheesh Paul 		 */
13808ca851cdSSatheesh Paul 		tx_vtag_action.act.vtag1_relptr =
13818ca851cdSSatheesh Paul 			NIX_TX_VTAGACTION_VTAG0_RELPTR;
13828ca851cdSSatheesh Paul 	}
13838ca851cdSSatheesh Paul 
13848ca851cdSSatheesh Paul 	flow->vtag_action = tx_vtag_action.reg;
13858ca851cdSSatheesh Paul 
138644a9307cSRakesh Kudurumalla 	rc = 0;
138744a9307cSRakesh Kudurumalla exit:
138844a9307cSRakesh Kudurumalla 	mbox_put(mbox);
138944a9307cSRakesh Kudurumalla 	return rc;
13908ca851cdSSatheesh Paul }
13918ca851cdSSatheesh Paul 
13928ca851cdSSatheesh Paul static int
13938ca851cdSSatheesh Paul npc_vtag_strip_action_configure(struct mbox *mbox,
13948ca851cdSSatheesh Paul 				const struct roc_npc_action actions[],
13958ca851cdSSatheesh Paul 				struct roc_npc_flow *flow, int *strip_cnt)
13968ca851cdSSatheesh Paul {
13978ca851cdSSatheesh Paul 	struct nix_vtag_config *vtag_cfg;
13988ca851cdSSatheesh Paul 	uint64_t rx_vtag_action = 0;
13998ca851cdSSatheesh Paul 	int count = 0, rc = 0;
14008ca851cdSSatheesh Paul 
14018ca851cdSSatheesh Paul 	*strip_cnt = 0;
14028ca851cdSSatheesh Paul 
14038ca851cdSSatheesh Paul 	for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) {
14048ca851cdSSatheesh Paul 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP)
14058ca851cdSSatheesh Paul 			(*strip_cnt)++;
14068ca851cdSSatheesh Paul 	}
14078ca851cdSSatheesh Paul 
140844a9307cSRakesh Kudurumalla 	vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox_get(mbox));
140919f3cc23SSatheesh Paul 
141044a9307cSRakesh Kudurumalla 	if (vtag_cfg == NULL) {
141144a9307cSRakesh Kudurumalla 		rc = -ENOSPC;
141244a9307cSRakesh Kudurumalla 		goto exit;
141344a9307cSRakesh Kudurumalla 	}
141419f3cc23SSatheesh Paul 
141519f3cc23SSatheesh Paul 	vtag_cfg->cfg_type = VTAG_RX;
141619f3cc23SSatheesh Paul 	vtag_cfg->rx.strip_vtag = 1;
141719f3cc23SSatheesh Paul 	/* Always capture */
141819f3cc23SSatheesh Paul 	vtag_cfg->rx.capture_vtag = 1;
141919f3cc23SSatheesh Paul 	vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
142019f3cc23SSatheesh Paul 	vtag_cfg->rx.vtag_type = 0;
142119f3cc23SSatheesh Paul 
142219f3cc23SSatheesh Paul 	rc = mbox_process(mbox);
142319f3cc23SSatheesh Paul 	if (rc)
142444a9307cSRakesh Kudurumalla 		goto exit;
142519f3cc23SSatheesh Paul 
142619f3cc23SSatheesh Paul 	rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
142719f3cc23SSatheesh Paul 	rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8);
1428296e9040SKiran Kumar K 	rx_vtag_action |= ((uint64_t)NIX_RX_VTAG_TYPE6 << 12);
142919f3cc23SSatheesh Paul 	rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
14308ca851cdSSatheesh Paul 
14318ca851cdSSatheesh Paul 	if (*strip_cnt == 2) {
14328ca851cdSSatheesh Paul 		rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47);
14338ca851cdSSatheesh Paul 		rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40);
14348ca851cdSSatheesh Paul 		rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32;
14358ca851cdSSatheesh Paul 	}
143619f3cc23SSatheesh Paul 	flow->vtag_action = rx_vtag_action;
14378ca851cdSSatheesh Paul 
143844a9307cSRakesh Kudurumalla 	rc = 0;
143944a9307cSRakesh Kudurumalla exit:
144044a9307cSRakesh Kudurumalla 	mbox_put(mbox);
144144a9307cSRakesh Kudurumalla 	return rc;
14428ca851cdSSatheesh Paul }
14438ca851cdSSatheesh Paul 
14448ca851cdSSatheesh Paul static int
14458ca851cdSSatheesh Paul npc_vtag_action_program(struct roc_npc *roc_npc,
14468ca851cdSSatheesh Paul 			const struct roc_npc_action actions[],
14478ca851cdSSatheesh Paul 			struct roc_npc_flow *flow)
14488ca851cdSSatheesh Paul {
14498ca851cdSSatheesh Paul 	bool vlan_strip_parsed = false, vlan_insert_parsed = false;
14508ca851cdSSatheesh Paul 	const struct roc_npc_action *insert_actions;
14518ca851cdSSatheesh Paul 	struct roc_nix *roc_nix = roc_npc->roc_nix;
14528ca851cdSSatheesh Paul 	struct npc_action_vtag_info vlan_info[2];
14538ca851cdSSatheesh Paul 	int parsed_cnt = 0, strip_cnt = 0;
14548ca851cdSSatheesh Paul 	int tot_vlan_params = 0;
14558ca851cdSSatheesh Paul 	struct mbox *mbox;
14568ca851cdSSatheesh Paul 	struct nix *nix;
14578ca851cdSSatheesh Paul 	int i, rc;
14588ca851cdSSatheesh Paul 
14598ca851cdSSatheesh Paul 	nix = roc_nix_to_nix_priv(roc_nix);
14608ca851cdSSatheesh Paul 	mbox = (&nix->dev)->mbox;
1461296e9040SKiran Kumar K 	if (flow->has_rep)
1462296e9040SKiran Kumar K 		mbox = flow->rep_mbox;
14638ca851cdSSatheesh Paul 
14648ca851cdSSatheesh Paul 	memset(vlan_info, 0, sizeof(vlan_info));
14658ca851cdSSatheesh Paul 
14668ca851cdSSatheesh Paul 	flow->vtag_insert_enabled = false;
14678ca851cdSSatheesh Paul 
14688ca851cdSSatheesh Paul 	for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) {
14698ca851cdSSatheesh Paul 		if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) {
14708ca851cdSSatheesh Paul 			if (vlan_strip_parsed) {
14718ca851cdSSatheesh Paul 				plt_err("Incorrect VLAN strip actions");
147219f3cc23SSatheesh Paul 				return -EINVAL;
147319f3cc23SSatheesh Paul 			}
14748ca851cdSSatheesh Paul 			rc = npc_vtag_strip_action_configure(mbox, actions,
14758ca851cdSSatheesh Paul 							     flow, &strip_cnt);
14768ca851cdSSatheesh Paul 			if (rc)
14778ca851cdSSatheesh Paul 				return rc;
14788ca851cdSSatheesh Paul 
1479296e9040SKiran Kumar K 			plt_npc_dbg("VLAN strip action, strip_cnt %d", strip_cnt);
14808ca851cdSSatheesh Paul 			if (strip_cnt == 2)
14818ca851cdSSatheesh Paul 				actions++;
14828ca851cdSSatheesh Paul 
14838ca851cdSSatheesh Paul 			vlan_strip_parsed = true;
14848ca851cdSSatheesh Paul 		} else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT ||
14858ca851cdSSatheesh Paul 			   actions->type ==
14868ca851cdSSatheesh Paul 				   ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT ||
14878ca851cdSSatheesh Paul 			   actions->type ==
148819f3cc23SSatheesh Paul 				   ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) {
14898ca851cdSSatheesh Paul 			if (vlan_insert_parsed) {
14908ca851cdSSatheesh Paul 				plt_err("Incorrect VLAN insert actions");
149119f3cc23SSatheesh Paul 				return -EINVAL;
149219f3cc23SSatheesh Paul 			}
14938ca851cdSSatheesh Paul 
14948ca851cdSSatheesh Paul 			insert_actions = actions;
14958ca851cdSSatheesh Paul 
14968ca851cdSSatheesh Paul 			for (i = 0; i < 2; i++) {
14978ca851cdSSatheesh Paul 				rc = npc_vtag_insert_action_parse(
14988ca851cdSSatheesh Paul 					insert_actions, flow, &vlan_info[i],
14998ca851cdSSatheesh Paul 					&parsed_cnt);
15008ca851cdSSatheesh Paul 
15018ca851cdSSatheesh Paul 				if (rc)
15028ca851cdSSatheesh Paul 					return rc;
15038ca851cdSSatheesh Paul 
15048ca851cdSSatheesh Paul 				if (parsed_cnt) {
15058ca851cdSSatheesh Paul 					insert_actions += parsed_cnt;
15068ca851cdSSatheesh Paul 					tot_vlan_params += parsed_cnt;
15078ca851cdSSatheesh Paul 					flow->vtag_insert_count++;
15088ca851cdSSatheesh Paul 				}
15098ca851cdSSatheesh Paul 			}
15108ca851cdSSatheesh Paul 			actions += tot_vlan_params - 1;
15118ca851cdSSatheesh Paul 			vlan_insert_parsed = true;
151219f3cc23SSatheesh Paul 		}
151319f3cc23SSatheesh Paul 	}
151419f3cc23SSatheesh Paul 
151519f3cc23SSatheesh Paul 	if (flow->vtag_insert_enabled) {
15168ca851cdSSatheesh Paul 		rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info);
151719f3cc23SSatheesh Paul 
151819f3cc23SSatheesh Paul 		if (rc)
151919f3cc23SSatheesh Paul 			return rc;
152019f3cc23SSatheesh Paul 	}
152119f3cc23SSatheesh Paul 	return 0;
152219f3cc23SSatheesh Paul }
152319f3cc23SSatheesh Paul 
1524df5cf15fSKiran Kumar K static int
1525df5cf15fSKiran Kumar K npc_inline_dev_ipsec_action_free(struct npc *npc, struct roc_npc_flow *flow)
1526df5cf15fSKiran Kumar K {
1527df5cf15fSKiran Kumar K 	struct nix_inl_dev *inl_dev;
1528df5cf15fSKiran Kumar K 	struct idev_cfg *idev;
1529df5cf15fSKiran Kumar K 	int rc;
1530df5cf15fSKiran Kumar K 
1531df5cf15fSKiran Kumar K 	PLT_SET_USED(npc);
1532df5cf15fSKiran Kumar K 
1533df5cf15fSKiran Kumar K 	idev = idev_get_cfg();
1534df5cf15fSKiran Kumar K 	if (!idev)
1535df5cf15fSKiran Kumar K 		return 1;
1536df5cf15fSKiran Kumar K 
1537df5cf15fSKiran Kumar K 	inl_dev = idev->nix_inl_dev;
1538df5cf15fSKiran Kumar K 
1539df5cf15fSKiran Kumar K 	if (flow->nix_intf == NIX_INTF_RX && inl_dev && inl_dev->ipsec_index &&
1540df5cf15fSKiran Kumar K 	    ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_UCAST_IPSEC)) {
1541df5cf15fSKiran Kumar K 		inl_dev->curr_ipsec_idx--;
1542df5cf15fSKiran Kumar K 		inl_dev->ipsec_index[inl_dev->curr_ipsec_idx] = flow->mcam_id;
1543df5cf15fSKiran Kumar K 		flow->enable = 0;
1544df5cf15fSKiran Kumar K 		if (flow->use_ctr) {
1545df5cf15fSKiran Kumar K 			rc = npc_mcam_clear_counter(inl_dev->dev.mbox, flow->ctr_id);
1546df5cf15fSKiran Kumar K 			if (rc)
1547df5cf15fSKiran Kumar K 				return rc;
1548df5cf15fSKiran Kumar K 
1549df5cf15fSKiran Kumar K 			rc = npc_mcam_free_counter(inl_dev->dev.mbox, flow->ctr_id);
1550df5cf15fSKiran Kumar K 			if (rc)
1551df5cf15fSKiran Kumar K 				return rc;
1552df5cf15fSKiran Kumar K 		}
1553df5cf15fSKiran Kumar K 		return npc_mcam_write_entry(inl_dev->dev.mbox, flow);
1554df5cf15fSKiran Kumar K 	}
1555df5cf15fSKiran Kumar K 
1556df5cf15fSKiran Kumar K 	return 1;
1557df5cf15fSKiran Kumar K }
1558df5cf15fSKiran Kumar K 
1559fd493460SSatheesh Paul void
15602703f1faSSatheesh Paul roc_npc_sdp_channel_get(struct roc_npc *roc_npc, uint16_t *chan_base, uint16_t *chan_mask)
15612703f1faSSatheesh Paul {
15622703f1faSSatheesh Paul 	struct roc_nix *roc_nix = roc_npc->roc_nix;
15632703f1faSSatheesh Paul 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
15642703f1faSSatheesh Paul 	uint16_t num_chan, range, num_bits = 0;
15652703f1faSSatheesh Paul 	uint16_t mask = 0;
15662703f1faSSatheesh Paul 
15672703f1faSSatheesh Paul 	*chan_base = nix->rx_chan_base;
15682703f1faSSatheesh Paul 	num_chan = nix->rx_chan_cnt - 1;
15692703f1faSSatheesh Paul 	if (num_chan) {
15702703f1faSSatheesh Paul 		range = *chan_base ^ (*chan_base + num_chan);
1571354bf671SJerin Jacob 		num_bits = (sizeof(uint32_t) * 8) - plt_clz32(range) - 1;
15722703f1faSSatheesh Paul 		/* Set mask for (15 - numbits) MSB bits */
15732703f1faSSatheesh Paul 		*chan_mask = (uint16_t)~GENMASK(num_bits, 0);
1574fd493460SSatheesh Paul 		*chan_mask &= 0xFFF;
15752703f1faSSatheesh Paul 	} else {
1576fd493460SSatheesh Paul 		*chan_mask = (uint16_t)GENMASK(11, 0);
15772703f1faSSatheesh Paul 	}
15782703f1faSSatheesh Paul 
15792703f1faSSatheesh Paul 	mask = (uint16_t)GENMASK(num_bits, 0);
15802703f1faSSatheesh Paul 	if (mask > num_chan + 1)
15812703f1faSSatheesh Paul 		plt_warn(
15822703f1faSSatheesh Paul 			"npc: SDP channel base:%x, channel count:%x. channel mask:%x covers more than channel count",
15832703f1faSSatheesh Paul 			*chan_base, nix->rx_chan_cnt, *chan_mask);
15842703f1faSSatheesh Paul }
15852703f1faSSatheesh Paul 
1586a07f7cedSKiran Kumar K struct roc_npc_flow *
1587a07f7cedSKiran Kumar K roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr,
1588b7eb0e0cSSatheesh Paul 		    const struct roc_npc_item_info pattern[], const struct roc_npc_action actions[],
1589b7eb0e0cSSatheesh Paul 		    uint16_t dst_pf_func, int *errcode)
1590a07f7cedSKiran Kumar K {
1591a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
15922703f1faSSatheesh Paul 	uint16_t sdp_chan_base = 0, sdp_chan_mask = 0;
1593a07f7cedSKiran Kumar K 	struct roc_npc_flow *flow, *flow_iter;
1594a07f7cedSKiran Kumar K 	struct npc_parse_state parse_state;
1595a07f7cedSKiran Kumar K 	struct npc_flow_list *list;
1596a07f7cedSKiran Kumar K 	int rc;
1597a07f7cedSKiran Kumar K 
1598d43a7beeSSatheesh Paul 	npc->channel = roc_npc->channel;
1599f1375663SSatheesh Paul 	npc->is_sdp_link = roc_nix_is_sdp(roc_npc->roc_nix);
1600f1375663SSatheesh Paul 	if (npc->is_sdp_link) {
1601f1375663SSatheesh Paul 		if (roc_npc->is_sdp_mask_set) {
1602f1375663SSatheesh Paul 			npc->sdp_channel = roc_npc->sdp_channel;
1603f1375663SSatheesh Paul 			npc->sdp_channel_mask = roc_npc->sdp_channel_mask;
1604f1375663SSatheesh Paul 		} else {
16052703f1faSSatheesh Paul 			roc_npc_sdp_channel_get(roc_npc, &sdp_chan_base, &sdp_chan_mask);
16062703f1faSSatheesh Paul 			npc->sdp_channel = sdp_chan_base;
16072703f1faSSatheesh Paul 			npc->sdp_channel_mask = sdp_chan_mask;
1608f1375663SSatheesh Paul 		}
1609b182b227SSatheesh Paul 	}
1610d43a7beeSSatheesh Paul 
1611a07f7cedSKiran Kumar K 	flow = plt_zmalloc(sizeof(*flow), 0);
1612a07f7cedSKiran Kumar K 	if (flow == NULL) {
1613a07f7cedSKiran Kumar K 		*errcode = NPC_ERR_NO_MEM;
1614a07f7cedSKiran Kumar K 		return NULL;
1615a07f7cedSKiran Kumar K 	}
1616a07f7cedSKiran Kumar K 	memset(flow, 0, sizeof(*flow));
1617b7fff4e4SSatheesh Paul 	memset(&parse_state, 0, sizeof(parse_state));
1618a07f7cedSKiran Kumar K 
1619296e9040SKiran Kumar K 	flow->port_id = -1;
1620296e9040SKiran Kumar K 	if (roc_npc->rep_npc) {
1621296e9040SKiran Kumar K 		flow->rep_channel =
1622296e9040SKiran Kumar K 			(roc_npc->rep_rx_channel == 0) ?
1623296e9040SKiran Kumar K 				roc_nix_to_nix_priv(roc_npc->rep_npc->roc_nix)->rx_chan_base :
1624296e9040SKiran Kumar K 				roc_npc->rep_rx_channel;
1625296e9040SKiran Kumar K 		flow->rep_pf_func = roc_npc->rep_pf_func;
1626296e9040SKiran Kumar K 		flow->rep_act_pf_func = roc_npc->rep_act_pf_func;
1627296e9040SKiran Kumar K 		flow->rep_act_rep = roc_npc->rep_act_rep;
1628296e9040SKiran Kumar K 		flow->rep_mbox = roc_npc_to_npc_priv(roc_npc->rep_npc)->mbox;
1629296e9040SKiran Kumar K 		flow->has_rep = true;
1630296e9040SKiran Kumar K 		flow->is_rep_vf = !roc_nix_is_pf(roc_npc->rep_npc->roc_nix);
1631296e9040SKiran Kumar K 		flow->port_id = roc_npc->rep_port_id;
1632296e9040SKiran Kumar K 		flow->rep_npc = roc_npc_to_npc_priv(roc_npc->rep_npc);
1633296e9040SKiran Kumar K 		roc_npc->rep_act_rep = false;
1634296e9040SKiran Kumar K 		roc_npc->rep_act_pf_func = 0;
1635296e9040SKiran Kumar K 		roc_npc->rep_rx_channel = 0;
1636296e9040SKiran Kumar K 	}
1637296e9040SKiran Kumar K 
1638b7eb0e0cSSatheesh Paul 	parse_state.dst_pf_func = dst_pf_func;
1639b7eb0e0cSSatheesh Paul 
1640b7eb0e0cSSatheesh Paul 	rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, &parse_state);
1641a07f7cedSKiran Kumar K 	if (rc != 0) {
1642a07f7cedSKiran Kumar K 		*errcode = rc;
1643a07f7cedSKiran Kumar K 		goto err_exit;
1644a07f7cedSKiran Kumar K 	}
1645a07f7cedSKiran Kumar K 
164619f3cc23SSatheesh Paul 	rc = npc_vtag_action_program(roc_npc, actions, flow);
164719f3cc23SSatheesh Paul 	if (rc != 0) {
164819f3cc23SSatheesh Paul 		*errcode = rc;
164919f3cc23SSatheesh Paul 		goto err_exit;
165019f3cc23SSatheesh Paul 	}
165119f3cc23SSatheesh Paul 
1652a07f7cedSKiran Kumar K 	parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix);
1653a07f7cedSKiran Kumar K 
1654a07f7cedSKiran Kumar K 	rc = npc_program_mcam(npc, &parse_state, 1);
1655a07f7cedSKiran Kumar K 	if (rc != 0) {
1656a07f7cedSKiran Kumar K 		*errcode = rc;
1657a07f7cedSKiran Kumar K 		goto err_exit;
1658a07f7cedSKiran Kumar K 	}
1659a07f7cedSKiran Kumar K 
166031525923SSatha Rao 	/* If Egress mirror requested then enable TL3_TL2_LINK_CFG */
166131525923SSatha Rao 	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
166231525923SSatha Rao 		if (flow->mcast_pf_funcs[0] == npc->pf_func)
166331525923SSatha Rao 			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
166431525923SSatha Rao 							    flow->mcast_pf_funcs[1], true);
166531525923SSatha Rao 		else
166631525923SSatha Rao 			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
166731525923SSatha Rao 							    flow->mcast_pf_funcs[0], true);
166831525923SSatha Rao 		if (rc) {
166931525923SSatha Rao 			plt_err("Adding egress mirror failed");
167031525923SSatha Rao 			*errcode = rc;
167131525923SSatha Rao 			goto err_exit;
167231525923SSatha Rao 		}
167331525923SSatha Rao 	}
167431525923SSatha Rao 
167551dc6a80SSatheesh Paul 	rc = npc_rss_action_program(roc_npc, actions, flow);
167651dc6a80SSatheesh Paul 	if (rc != 0) {
167751dc6a80SSatheesh Paul 		*errcode = rc;
167851dc6a80SSatheesh Paul 		goto set_rss_failed;
167951dc6a80SSatheesh Paul 	}
1680296e9040SKiran Kumar K 	roc_npc->rep_npc = NULL;
1681*29a8df5cSHarman Kalra 	roc_npc->rep_act_pf_func = 0;
168251dc6a80SSatheesh Paul 
1683c436ab84SAnkur Dwivedi 	if (flow->has_age_action)
1684c436ab84SAnkur Dwivedi 		npc_age_flow_list_entry_add(roc_npc, flow);
1685c436ab84SAnkur Dwivedi 
1686df5cf15fSKiran Kumar K 	if (flow->use_pre_alloc == 0)
1687a07f7cedSKiran Kumar K 		list = &npc->flow_list[flow->priority];
1688df5cf15fSKiran Kumar K 	else
1689df5cf15fSKiran Kumar K 		list = &npc->ipsec_list;
1690a07f7cedSKiran Kumar K 	/* List in ascending order of mcam entries */
1691a07f7cedSKiran Kumar K 	TAILQ_FOREACH(flow_iter, list, next) {
1692a07f7cedSKiran Kumar K 		if (flow_iter->mcam_id > flow->mcam_id) {
1693a07f7cedSKiran Kumar K 			TAILQ_INSERT_BEFORE(flow_iter, flow, next);
1694296e9040SKiran Kumar K 			roc_npc->rep_npc = NULL;
1695a07f7cedSKiran Kumar K 			return flow;
1696a07f7cedSKiran Kumar K 		}
1697a07f7cedSKiran Kumar K 	}
1698a07f7cedSKiran Kumar K 	TAILQ_INSERT_TAIL(list, flow, next);
1699357f5ebcSAnkur Dwivedi 
1700a07f7cedSKiran Kumar K 	return flow;
1701a07f7cedSKiran Kumar K 
170251dc6a80SSatheesh Paul set_rss_failed:
1703296e9040SKiran Kumar K 	roc_npc->rep_npc = NULL;
1704*29a8df5cSHarman Kalra 	roc_npc->rep_act_pf_func = 0;
1705df5cf15fSKiran Kumar K 	if (flow->use_pre_alloc == 0) {
170622d9d348SSatheesh Paul 		rc = roc_npc_mcam_free_entry(roc_npc, flow->mcam_id);
170751dc6a80SSatheesh Paul 		if (rc != 0) {
170851dc6a80SSatheesh Paul 			*errcode = rc;
170951dc6a80SSatheesh Paul 			plt_free(flow);
171051dc6a80SSatheesh Paul 			return NULL;
171151dc6a80SSatheesh Paul 		}
1712df5cf15fSKiran Kumar K 	} else {
1713df5cf15fSKiran Kumar K 		npc_inline_dev_ipsec_action_free(npc, flow);
1714df5cf15fSKiran Kumar K 	}
1715a07f7cedSKiran Kumar K err_exit:
1716296e9040SKiran Kumar K 	roc_npc->rep_npc = NULL;
1717*29a8df5cSHarman Kalra 	roc_npc->rep_act_pf_func = 0;
1718a07f7cedSKiran Kumar K 	plt_free(flow);
1719a07f7cedSKiran Kumar K 	return NULL;
1720a07f7cedSKiran Kumar K }
1721a07f7cedSKiran Kumar K 
1722a07f7cedSKiran Kumar K int
172351dc6a80SSatheesh Paul npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow)
172451dc6a80SSatheesh Paul {
1725296e9040SKiran Kumar K 	struct npc *lnpc = npc;
172651dc6a80SSatheesh Paul 	uint32_t rss_grp;
172751dc6a80SSatheesh Paul 
1728296e9040SKiran Kumar K 	if (flow->has_rep)
1729296e9040SKiran Kumar K 		lnpc = flow->rep_npc;
1730296e9040SKiran Kumar K 
173151dc6a80SSatheesh Paul 	if ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_RSS) {
173251dc6a80SSatheesh Paul 		rss_grp = (flow->npc_action >> NPC_RSS_ACT_GRP_OFFSET) &
173351dc6a80SSatheesh Paul 			  NPC_RSS_ACT_GRP_MASK;
173451dc6a80SSatheesh Paul 		if (rss_grp == 0 || rss_grp >= npc->rss_grps)
173551dc6a80SSatheesh Paul 			return -EINVAL;
173651dc6a80SSatheesh Paul 
1737296e9040SKiran Kumar K 		plt_bitmap_clear(lnpc->rss_grp_entries, rss_grp);
173851dc6a80SSatheesh Paul 	}
173951dc6a80SSatheesh Paul 
174051dc6a80SSatheesh Paul 	return 0;
174151dc6a80SSatheesh Paul }
174251dc6a80SSatheesh Paul 
174304087b78SSatheesh Paul static int
174404087b78SSatheesh Paul roc_npc_delete_spi_to_sa_action(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
174504087b78SSatheesh Paul {
174604087b78SSatheesh Paul 	struct nix_spi_to_sa_delete_req *req;
174760f0cf50SSatheesh Paul 	struct nix_inl_dev *inl_dev;
174860f0cf50SSatheesh Paul 	struct idev_cfg *idev;
174904087b78SSatheesh Paul 	struct mbox *mbox;
175060f0cf50SSatheesh Paul 
175160f0cf50SSatheesh Paul 	PLT_SET_USED(roc_npc);
175204087b78SSatheesh Paul 
175304087b78SSatheesh Paul 	if (!flow->spi_to_sa_info.has_action || flow->spi_to_sa_info.duplicate)
175404087b78SSatheesh Paul 		return 0;
175504087b78SSatheesh Paul 
175660f0cf50SSatheesh Paul 	idev = idev_get_cfg();
175760f0cf50SSatheesh Paul 	if (!idev)
175860f0cf50SSatheesh Paul 		return -1;
175960f0cf50SSatheesh Paul 
176060f0cf50SSatheesh Paul 	inl_dev = idev->nix_inl_dev;
176160f0cf50SSatheesh Paul 	mbox = inl_dev->dev.mbox;
176204087b78SSatheesh Paul 	req = mbox_alloc_msg_nix_spi_to_sa_delete(mbox);
176304087b78SSatheesh Paul 	if (req == NULL)
176404087b78SSatheesh Paul 		return -ENOSPC;
176504087b78SSatheesh Paul 	req->hash_index = flow->spi_to_sa_info.hash_index;
176604087b78SSatheesh Paul 	req->way = flow->spi_to_sa_info.way;
176704087b78SSatheesh Paul 	return mbox_process_msg(mbox, NULL);
176804087b78SSatheesh Paul }
176904087b78SSatheesh Paul 
177051dc6a80SSatheesh Paul int
1771a07f7cedSKiran Kumar K roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
1772a07f7cedSKiran Kumar K {
1773a07f7cedSKiran Kumar K 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
1774a07f7cedSKiran Kumar K 	int rc;
1775a07f7cedSKiran Kumar K 
177604087b78SSatheesh Paul 	rc = roc_npc_delete_spi_to_sa_action(roc_npc, flow);
177704087b78SSatheesh Paul 	if (rc)
177804087b78SSatheesh Paul 		return rc;
177904087b78SSatheesh Paul 
1780df5cf15fSKiran Kumar K 	if (npc_inline_dev_ipsec_action_free(npc, flow) == 0) {
1781df5cf15fSKiran Kumar K 		TAILQ_REMOVE(&npc->ipsec_list, flow, next);
1782df5cf15fSKiran Kumar K 		goto done;
1783df5cf15fSKiran Kumar K 	}
1784df5cf15fSKiran Kumar K 
178551dc6a80SSatheesh Paul 	rc = npc_rss_group_free(npc, flow);
178651dc6a80SSatheesh Paul 	if (rc != 0) {
178751dc6a80SSatheesh Paul 		plt_err("Failed to free rss action rc = %d", rc);
178851dc6a80SSatheesh Paul 		return rc;
178951dc6a80SSatheesh Paul 	}
179051dc6a80SSatheesh Paul 
179119f3cc23SSatheesh Paul 	if (flow->vtag_insert_enabled) {
179219f3cc23SSatheesh Paul 		rc = npc_vtag_cfg_delete(roc_npc, flow);
179319f3cc23SSatheesh Paul 		if (rc != 0)
179419f3cc23SSatheesh Paul 			return rc;
179519f3cc23SSatheesh Paul 	}
179619f3cc23SSatheesh Paul 
179731525923SSatha Rao 	/* Disable egress mirror rule */
179831525923SSatha Rao 	if (flow->is_sampling_rule && (flow->nix_intf == NIX_INTF_TX)) {
179931525923SSatha Rao 		if (flow->mcast_pf_funcs[0] == npc->pf_func)
180031525923SSatha Rao 			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
180131525923SSatha Rao 							    flow->mcast_pf_funcs[1], false);
180231525923SSatha Rao 		else
180331525923SSatha Rao 			rc = roc_nix_tm_egress_link_cfg_set(roc_npc->roc_nix,
180431525923SSatha Rao 							    flow->mcast_pf_funcs[0], false);
180531525923SSatha Rao 		if (rc)
180631525923SSatha Rao 			plt_err("Failed to remove egress mirror rule");
180731525923SSatha Rao 	}
1808209188d1SSatheesh Paul 	if (flow->is_sampling_rule)
1809209188d1SSatheesh Paul 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
1810209188d1SSatheesh Paul 
181122d9d348SSatheesh Paul 	rc = roc_npc_mcam_free(roc_npc, flow);
1812a07f7cedSKiran Kumar K 	if (rc != 0)
1813a07f7cedSKiran Kumar K 		return rc;
1814a07f7cedSKiran Kumar K 
1815a07f7cedSKiran Kumar K 	TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next);
1816a07f7cedSKiran Kumar K 
18171f669198SSatheesh Paul 	npc_delete_prio_list_entry(npc, flow);
1818a07f7cedSKiran Kumar K 
1819c436ab84SAnkur Dwivedi 	if (flow->has_age_action)
1820357f5ebcSAnkur Dwivedi 		npc_age_flow_list_entry_delete(roc_npc, flow);
1821c436ab84SAnkur Dwivedi 
182285e9542dSSatheesh Paul 	if (roc_npc->flow_age.age_flow_refcnt == 0)
1823357f5ebcSAnkur Dwivedi 		npc_aging_ctrl_thread_destroy(roc_npc);
1824357f5ebcSAnkur Dwivedi 
1825df5cf15fSKiran Kumar K done:
1826a07f7cedSKiran Kumar K 	plt_free(flow);
1827a07f7cedSKiran Kumar K 	return 0;
1828a07f7cedSKiran Kumar K }
18299869c399SSatheesh Paul 
18309869c399SSatheesh Paul void
1831296e9040SKiran Kumar K roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc, int rep_port_id)
18329869c399SSatheesh Paul {
18339869c399SSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
18349869c399SSatheesh Paul 	struct roc_npc_flow *flow_iter;
18359869c399SSatheesh Paul 	struct npc_flow_list *list;
18369869c399SSatheesh Paul 	uint32_t max_prio, i;
18379869c399SSatheesh Paul 
18389869c399SSatheesh Paul 	max_prio = npc->flow_max_priority;
18399869c399SSatheesh Paul 
18409869c399SSatheesh Paul 	for (i = 0; i < max_prio; i++) {
18419869c399SSatheesh Paul 		list = &npc->flow_list[i];
18429869c399SSatheesh Paul 
18439869c399SSatheesh Paul 		/* List in ascending order of mcam entries */
18449869c399SSatheesh Paul 		TAILQ_FOREACH(flow_iter, list, next) {
1845296e9040SKiran Kumar K 			if (rep_port_id == -1 || rep_port_id == flow_iter->port_id)
18469869c399SSatheesh Paul 				roc_npc_flow_mcam_dump(file, roc_npc, flow_iter);
18479869c399SSatheesh Paul 		}
18489869c399SSatheesh Paul 	}
184944550b64SSatheesh Paul 
185044550b64SSatheesh Paul 	TAILQ_FOREACH(flow_iter, &npc->ipsec_list, next) {
1851296e9040SKiran Kumar K 		if (rep_port_id == -1 || rep_port_id == flow_iter->port_id)
185244550b64SSatheesh Paul 			roc_npc_flow_mcam_dump(file, roc_npc, flow_iter);
185344550b64SSatheesh Paul 	}
18549869c399SSatheesh Paul }
18550cc909ccSSatheesh Paul 
18560cc909ccSSatheesh Paul int
185744550b64SSatheesh Paul roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
18580cc909ccSSatheesh Paul {
18590cc909ccSSatheesh Paul 	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
18600cc909ccSSatheesh Paul 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
18610cc909ccSSatheesh Paul 	struct mcam_entry *base_entry;
186244a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get(npc->mbox);
18630cc909ccSSatheesh Paul 	int idx, rc;
18640cc909ccSSatheesh Paul 
186544a9307cSRakesh Kudurumalla 	if (roc_nix_is_pf(roc_npc->roc_nix)) {
186644a9307cSRakesh Kudurumalla 		rc = 0;
186744a9307cSRakesh Kudurumalla 		goto exit;
186844a9307cSRakesh Kudurumalla 	}
18690cc909ccSSatheesh Paul 
187044a9307cSRakesh Kudurumalla 	(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
187144a9307cSRakesh Kudurumalla 	rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
18720cc909ccSSatheesh Paul 	if (rc) {
18730cc909ccSSatheesh Paul 		plt_err("Failed to fetch VF's base MCAM entry");
187444a9307cSRakesh Kudurumalla 		goto exit;
18750cc909ccSSatheesh Paul 	}
18760cc909ccSSatheesh Paul 	base_entry = &base_rule_rsp->entry_data;
18770cc909ccSSatheesh Paul 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
18780cc909ccSSatheesh Paul 		flow->mcam_data[idx] |= base_entry->kw[idx];
18790cc909ccSSatheesh Paul 		flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
18800cc909ccSSatheesh Paul 	}
18810cc909ccSSatheesh Paul 
188244a9307cSRakesh Kudurumalla 	rc = 0;
188344a9307cSRakesh Kudurumalla exit:
188444a9307cSRakesh Kudurumalla 	mbox_put(mbox);
188544a9307cSRakesh Kudurumalla 	return rc;
18860cc909ccSSatheesh Paul }
1887