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