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