common/mlx5: fix default devargs initialization
[dpdk.git] / drivers / net / cnxk / cnxk_ethdev_mtr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "cnxk_ethdev.h"
6 #include <rte_mtr_driver.h>
7
8 #define NIX_MTR_COUNT_MAX      73 /* 64(leaf) + 8(mid) + 1(top) */
9 #define NIX_MTR_COUNT_PER_FLOW 3  /* 1(leaf) + 1(mid) + 1(top) */
10
11 #define NIX_BPF_STATS_MASK_ALL                                                 \
12         {                                                                      \
13                 ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \
14                         ROC_NIX_BPF_GREEN_PKT_F_DROP |                         \
15                         ROC_NIX_BPF_GREEN_OCTS_F_DROP |                        \
16                         ROC_NIX_BPF_YELLOW_PKT_F_PASS |                        \
17                         ROC_NIX_BPF_YELLOW_OCTS_F_PASS |                       \
18                         ROC_NIX_BPF_YELLOW_PKT_F_DROP |                        \
19                         ROC_NIX_BPF_YELLOW_OCTS_F_DROP |                       \
20                         ROC_NIX_BPF_RED_PKT_F_PASS |                           \
21                         ROC_NIX_BPF_RED_OCTS_F_PASS |                          \
22                         ROC_NIX_BPF_RED_PKT_F_DROP |                           \
23                         ROC_NIX_BPF_RED_OCTS_F_DROP                            \
24         }
25
26 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
27                                                       ROC_NIX_BPF_LEVEL_F_MID,
28                                                       ROC_NIX_BPF_LEVEL_F_TOP};
29
30 static struct rte_mtr_capabilities mtr_capa = {
31         .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
32         /* .identical = , */
33         .shared_identical = true,
34         /* .shared_n_flows_per_mtr_max = ,*/
35         .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
36         .chaining_use_prev_mtr_color_supported = true,
37         .chaining_use_prev_mtr_color_enforced = true,
38         .color_aware_srtcm_rfc2697_supported = true,
39         .color_aware_trtcm_rfc2698_supported = true,
40         .color_aware_trtcm_rfc4115_supported = true,
41         .srtcm_rfc2697_byte_mode_supported = true,
42         .srtcm_rfc2697_packet_mode_supported = true,
43         .trtcm_rfc2698_byte_mode_supported = true,
44         .trtcm_rfc2698_packet_mode_supported = true,
45         .trtcm_rfc4115_byte_mode_supported = true,
46         .trtcm_rfc4115_packet_mode_supported = true,
47         .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
48                       RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
49                       RTE_MTR_STATS_N_BYTES_GREEN |
50                       RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
51                       RTE_MTR_STATS_N_BYTES_DROPPED};
52
53 static struct cnxk_meter_node *
54 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
55 {
56         struct cnxk_mtr *fms = &dev->mtr;
57         struct cnxk_meter_node *fm;
58
59         TAILQ_FOREACH(fm, fms, next)
60                 if (meter_id == fm->id)
61                         return fm;
62         return NULL;
63 }
64
65 static struct cnxk_mtr_profile_node *
66 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
67 {
68         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
69         struct cnxk_mtr_profile_node *fmp;
70
71         TAILQ_FOREACH(fmp, fmps, next)
72                 if (profile_id == fmp->id)
73                         return fmp;
74
75         return NULL;
76 }
77
78 static struct cnxk_mtr_policy_node *
79 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
80 {
81         struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
82         struct cnxk_mtr_policy_node *fmp;
83
84         TAILQ_FOREACH(fmp, fmps, next)
85                 if (meter_policy_id == fmp->id)
86                         return fmp;
87         return NULL;
88 }
89
90 static int
91 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
92                          struct rte_mtr_meter_profile *profile,
93                          struct rte_mtr_error *error)
94 {
95         int rc = 0;
96
97         PLT_SET_USED(dev);
98
99         if (profile == NULL)
100                 return -rte_mtr_error_set(error, EINVAL,
101                                           RTE_MTR_ERROR_TYPE_METER_PROFILE,
102                                           NULL, "Meter profile is null.");
103
104         if (profile_id == UINT32_MAX)
105                 return -rte_mtr_error_set(error, EINVAL,
106                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
107                                           NULL, "Meter profile id not valid.");
108
109         switch (profile->alg) {
110         case RTE_MTR_SRTCM_RFC2697:
111                 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
112                         rc = -rte_mtr_error_set(error, EINVAL,
113                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
114                                 "CIR exceeds max meter rate");
115
116                 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
117                         rc = -rte_mtr_error_set(error, EINVAL,
118                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
119                                 "CBS exceeds max meter burst size");
120
121                 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
122                         rc = -rte_mtr_error_set(error, EINVAL,
123                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
124                                 "EBS exceeds max meter burst size");
125                 break;
126
127         case RTE_MTR_TRTCM_RFC2698:
128                 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
129                         rc = -rte_mtr_error_set(error, EINVAL,
130                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
131                                 "CIR exceeds max meter rate");
132
133                 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
134                         rc = -rte_mtr_error_set(error, EINVAL,
135                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
136                                 "PIR exceeds max meter rate");
137
138                 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
139                         rc = -rte_mtr_error_set(error, EINVAL,
140                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
141                                 "CBS exceeds max meter burst size");
142
143                 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
144                         rc = -rte_mtr_error_set(error, EINVAL,
145                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
146                                 "PBS exceeds max meter burst size");
147                 break;
148
149         case RTE_MTR_TRTCM_RFC4115:
150                 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
151                     mtr_capa.meter_rate_max)
152                         rc = -rte_mtr_error_set(error, EINVAL,
153                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
154                                 "PIR + EIR exceeds max rate");
155
156                 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
157                         rc = -rte_mtr_error_set(error, EINVAL,
158                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
159                                 "CBS exceeds max meter burst size");
160
161                 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
162                         rc = -rte_mtr_error_set(error, EINVAL,
163                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
164                                 "PBS exceeds max meter burst size");
165                 break;
166
167         default:
168                 rc = -rte_mtr_error_set(error, EINVAL,
169                                         RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
170                                         "alg is invalid");
171                 break;
172         }
173
174         return rc;
175 }
176
177 static int
178 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
179                               struct rte_mtr_capabilities *capa,
180                               struct rte_mtr_error *error)
181 {
182         uint8_t lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF | ROC_NIX_BPF_LEVEL_F_MID |
183                            ROC_NIX_BPF_LEVEL_F_TOP;
184         struct cnxk_eth_dev *eth_dev = cnxk_eth_pmd_priv(dev);
185         uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0};
186         struct roc_nix *nix = &eth_dev->nix;
187         uint32_t time_unit;
188         int rc, i;
189
190         RTE_SET_USED(dev);
191
192         if (!capa)
193                 return -rte_mtr_error_set(error, EINVAL,
194                                 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
195                                 "NULL input parameter");
196
197         rc = roc_nix_bpf_count_get(nix, lvl_mask, count);
198         if (rc)
199                 return rc;
200
201         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++)
202                 mtr_capa.n_max += count[i];
203
204         mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max;
205         mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max;
206         mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max;
207         mtr_capa.meter_policy_n_max = mtr_capa.n_max;
208
209         rc = roc_nix_bpf_timeunit_get(nix, &time_unit);
210         if (rc)
211                 return rc;
212
213         mtr_capa.meter_rate_max =
214                 NIX_BPF_RATE(time_unit, NIX_BPF_MAX_RATE_EXPONENT,
215                              NIX_BPF_MAX_RATE_MANTISSA, 0) /
216                 8;
217
218         *capa = mtr_capa;
219         return 0;
220 }
221
222 static int
223 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
224                          struct rte_mtr_meter_profile *profile,
225                          struct rte_mtr_error *error)
226 {
227         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
228         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
229         struct cnxk_mtr_profile_node *fmp;
230         int ret;
231
232         /* Check input params. */
233         ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
234         if (ret)
235                 return ret;
236
237         fmp = nix_mtr_profile_find(dev, profile_id);
238         if (fmp) {
239                 return -rte_mtr_error_set(error, EEXIST,
240                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
241                                           NULL, "Profile already exist");
242         }
243
244         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
245         if (fmp == NULL)
246                 return -rte_mtr_error_set(error, ENOMEM,
247                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
248                                           "Meter profile memory "
249                                           "alloc failed.");
250
251         fmp->id = profile_id;
252         fmp->profile = *profile;
253
254         TAILQ_INSERT_TAIL(fmps, fmp, next);
255
256         return 0;
257 }
258
259 static int
260 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
261                             struct rte_mtr_error *error)
262 {
263         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
264         struct cnxk_mtr_profile_node *fmp;
265
266         if (profile_id == UINT32_MAX)
267                 return -rte_mtr_error_set(error, EINVAL,
268                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
269                                           NULL, "Meter profile id not valid.");
270
271         fmp = nix_mtr_profile_find(dev, profile_id);
272         if (fmp == NULL)
273                 return -rte_mtr_error_set(error, ENOENT,
274                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
275                                           &profile_id,
276                                           "Meter profile is invalid.");
277
278         if (fmp->ref_cnt)
279                 return -rte_mtr_error_set(error, EBUSY,
280                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
281                                           NULL, "Meter profile is in use.");
282
283         TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
284         plt_free(fmp);
285         return 0;
286 }
287
288 static int
289 update_mtr_err(uint32_t act_color, struct rte_mtr_error *error, bool action)
290 {
291         const char *str;
292         switch (act_color) {
293         case RTE_COLOR_GREEN:
294                 if (action) {
295                         str = "Green action is not valid";
296                         goto notsup;
297                 } else {
298                         str = "Green action is null";
299                         goto notvalid;
300                 }
301                 break;
302         case RTE_COLOR_YELLOW:
303                 if (action) {
304                         str = "Yellow action is not valid";
305                         goto notsup;
306                 } else {
307                         str = "Yellow action is null";
308                         goto notvalid;
309                 }
310                 break;
311         case RTE_COLOR_RED:
312                 if (action) {
313                         str = "Red action is not valid";
314                         goto notsup;
315                 } else {
316                         str = "Red action is null";
317                         goto notvalid;
318                 }
319                 break;
320         }
321 notsup:
322         return -rte_mtr_error_set(error, ENOTSUP,
323                                   RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
324 notvalid:
325         return -rte_mtr_error_set(error, EINVAL,
326                                   RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
327 }
328
329 static int
330 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
331                              struct rte_mtr_meter_policy_params *policy,
332                              struct rte_mtr_error *error)
333 {
334         bool supported[RTE_COLORS] = {false, false, false};
335         const struct rte_flow_action *action;
336         uint32_t i;
337
338         RTE_SET_USED(dev);
339
340         if (!policy)
341                 return 0; /* Nothing to be validated */
342
343         for (i = 0; i < RTE_COLORS; i++) {
344                 if (policy->actions[i]) {
345                         for (action = policy->actions[i];
346                              action->type != RTE_FLOW_ACTION_TYPE_END;
347                              action++) {
348                                 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
349                                         supported[i] = true;
350
351                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
352                                         supported[i] = true;
353
354                                 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
355                                         supported[i] = true;
356
357                                 if (!supported[i])
358                                         return update_mtr_err(i, error, true);
359                         }
360                 } else {
361                         return update_mtr_err(i, error, false);
362                 }
363         }
364
365         return 0;
366 }
367
368 static void
369 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
370                          struct rte_mtr_meter_policy_params *policy)
371
372 {
373         const struct rte_flow_action_meter *mtr;
374         const struct rte_flow_action *action;
375         int i;
376
377         for (i = 0; i < RTE_COLORS; i++) {
378                 if (policy->actions[i]) {
379                         for (action = policy->actions[i];
380                              action->type != RTE_FLOW_ACTION_TYPE_END;
381                              action++) {
382                                 if (action->type ==
383                                     RTE_FLOW_ACTION_TYPE_METER) {
384                                         fmp->actions[i].action_fate =
385                                                 action->type;
386                                         mtr = (const struct
387                                                rte_flow_action_meter *)
388                                                       action->conf;
389                                         fmp->actions[i].mtr_id = mtr->mtr_id;
390                                 }
391
392                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
393                                         fmp->actions[i].action_fate =
394                                                 action->type;
395                                 }
396                         }
397                 }
398         }
399 }
400
401 static int
402 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
403                         struct rte_mtr_meter_policy_params *policy,
404                         struct rte_mtr_error *error)
405 {
406         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
407         struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
408         struct cnxk_mtr_policy_node *fmp;
409         int rc;
410
411         fmp = nix_mtr_policy_find(dev, policy_id);
412         if (fmp) {
413                 return -rte_mtr_error_set(error, EEXIST,
414                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
415                                           NULL, "Policy already exist");
416         }
417
418         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
419         if (fmp == NULL) {
420                 return -rte_mtr_error_set(error, ENOMEM,
421                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
422                                           "Memory allocation failure");
423         } else {
424                 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
425                 if (rc)
426                         goto exit;
427         }
428
429         fmp->id = policy_id;
430         cnxk_fill_policy_actions(fmp, policy);
431         TAILQ_INSERT_TAIL(fmps, fmp, next);
432         return 0;
433
434 exit:
435         plt_free(fmp);
436         return rc;
437 }
438
439 static int
440 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
441                            struct rte_mtr_error *error)
442 {
443         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
444         struct cnxk_mtr_policy_node *fmp;
445
446         fmp = nix_mtr_policy_find(dev, policy_id);
447         if (fmp == NULL) {
448                 return -rte_mtr_error_set(error, ENOENT,
449                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
450                                           NULL, "No policy found");
451         }
452
453         if (fmp->ref_cnt)
454                 return -rte_mtr_error_set(error, EBUSY,
455                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
456                                           NULL, "Meter policy is in use.");
457
458         TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
459         plt_free(fmp);
460
461         return 0;
462 }
463
464 static int
465 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
466                     struct rte_mtr_params *params, int shared,
467                     struct rte_mtr_error *error)
468 {
469         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
470         struct cnxk_mtr_profile_node *profile;
471         struct cnxk_mtr_policy_node *policy;
472         struct cnxk_mtr *fm = &dev->mtr;
473         struct cnxk_meter_node *mtr;
474         int i;
475
476         RTE_SET_USED(shared);
477
478         if (params == NULL)
479                 return -rte_mtr_error_set(error, ENOENT,
480                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
481                                           "Meter params are invalid.");
482
483         profile = nix_mtr_profile_find(dev, params->meter_profile_id);
484         if (profile == NULL)
485                 return -rte_mtr_error_set(error, ENOENT,
486                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
487                                           &params->meter_profile_id,
488                                           "Meter profile is invalid.");
489
490         policy = nix_mtr_policy_find(dev, params->meter_policy_id);
491         if (policy == NULL)
492                 return -rte_mtr_error_set(error, ENOENT,
493                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
494                                           &params->meter_policy_id,
495                                           "Meter policy is invalid.");
496
497         mtr = nix_mtr_find(dev, mtr_id);
498         if (mtr) {
499                 return -rte_mtr_error_set(error, EEXIST,
500                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
501                                           "Meter already exist");
502         }
503
504         mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
505         if (mtr == NULL) {
506                 return -rte_mtr_error_set(error, ENOMEM,
507                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
508                                           "Meter memory alloc failed.");
509         }
510
511         mtr->id = mtr_id;
512         mtr->profile = profile;
513         mtr->policy = policy;
514         mtr->params = *params;
515         mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
516         mtr->prev_cnt = 0;
517         for (i = 0; i < MAX_PRV_MTR_NODES; i++)
518                 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
519
520         mtr->next_id = ROC_NIX_BPF_ID_INVALID;
521         mtr->is_next = false;
522         mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
523
524         if (params->dscp_table) {
525                 mtr->params.dscp_table =
526                         plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN);
527                 if (mtr->params.dscp_table == NULL) {
528                         plt_free(mtr);
529                         return -rte_mtr_error_set(error, ENOMEM,
530                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
531                                         NULL, "Memory alloc failed.");
532                 }
533
534                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
535                         mtr->params.dscp_table[i] = params->dscp_table[i];
536         }
537
538         profile->ref_cnt++;
539         policy->ref_cnt++;
540         TAILQ_INSERT_TAIL(fm, mtr, next);
541         return 0;
542 }
543
544 static int
545 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
546                      struct rte_mtr_error *error)
547 {
548         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
549         struct roc_nix_bpf_objs profs = {0};
550         struct cnxk_mtr *fm = &dev->mtr;
551         struct roc_nix *nix = &dev->nix;
552         struct cnxk_meter_node *mtr;
553         struct cnxk_meter_node *mid_mtr;
554         struct cnxk_meter_node *top_mtr;
555         int rc = 0;
556
557         mtr = nix_mtr_find(dev, mtr_id);
558         if (mtr == NULL) {
559                 return -rte_mtr_error_set(error, ENOENT,
560                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
561                                           "Meter id is invalid.");
562         }
563
564         if (mtr->ref_cnt) {
565                 return -rte_mtr_error_set(error, EADDRINUSE,
566                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
567                                           "Meter id in use.");
568         }
569
570         switch (lvl_map[mtr->level]) {
571         case ROC_NIX_BPF_LEVEL_F_LEAF:
572                 if (mtr->is_next) {
573                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
574                                                  mtr->bpf_id,
575                                                  ROC_NIX_BPF_ID_INVALID);
576                 }
577                 break;
578         case ROC_NIX_BPF_LEVEL_F_MID:
579                 while ((mtr->prev_cnt) + 1) {
580                         mid_mtr =
581                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
582                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
583                                                  mid_mtr->bpf_id,
584                                                  ROC_NIX_BPF_ID_INVALID);
585                         mtr->prev_cnt--;
586                 }
587                 if (mtr->is_next) {
588                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
589                                                  mtr->bpf_id,
590                                                  ROC_NIX_BPF_ID_INVALID);
591                 }
592                 break;
593         case ROC_NIX_BPF_LEVEL_F_TOP:
594                 while (mtr->prev_cnt) {
595                         top_mtr =
596                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
597                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
598                                                  top_mtr->bpf_id,
599                                                  ROC_NIX_BPF_ID_INVALID);
600                         mtr->prev_cnt--;
601                 }
602                 break;
603         default:
604                 return -rte_mtr_error_set(error, EINVAL,
605                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
606                                           "Invalid meter level");
607         }
608
609         if (rc)
610                 goto exit;
611
612         profs.level = mtr->level;
613         profs.count = 1;
614         profs.ids[0] = mtr->bpf_id;
615         rc = roc_nix_bpf_free(nix, &profs, 1);
616         if (rc)
617                 goto exit;
618
619         mtr->policy->ref_cnt--;
620         mtr->profile->ref_cnt--;
621         TAILQ_REMOVE(fm, mtr, next);
622         plt_free(mtr->params.dscp_table);
623         plt_free(mtr);
624
625 exit:
626         return rc;
627 }
628
629 static int
630 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
631                     struct rte_mtr_error *error)
632 {
633         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
634         struct roc_nix *nix = &dev->nix;
635         struct cnxk_meter_node *mtr;
636         struct roc_nix_rq *rq;
637         uint32_t i;
638         int rc = 0;
639
640         mtr = nix_mtr_find(dev, mtr_id);
641         if (mtr == NULL) {
642                 return -rte_mtr_error_set(error, ENOENT,
643                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
644                                           "Meter id is invalid.");
645         }
646
647         if (mtr->level != 0)
648                 return 0;
649
650         for (i = 0; i < mtr->rq_num; i++) {
651                 rq = &dev->rqs[mtr->rq_id[i]];
652                 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
653         }
654
655         return rc;
656 }
657
658 static int
659 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
660                      struct rte_mtr_error *error)
661 {
662         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
663         struct roc_nix *nix = &dev->nix;
664         struct cnxk_meter_node *mtr;
665         struct roc_nix_rq *rq;
666         uint32_t i;
667         int rc = 0;
668
669         mtr = nix_mtr_find(dev, mtr_id);
670         if (mtr == NULL) {
671                 return -rte_mtr_error_set(error, ENOENT,
672                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
673                                           "Meter id is invalid.");
674         }
675
676         if (mtr->level != 0)
677                 return 0;
678
679         for (i = 0; i < mtr->rq_num; i++) {
680                 rq = &dev->rqs[mtr->rq_id[i]];
681                 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
682         }
683
684         return rc;
685 }
686
687 static int
688 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
689                                enum rte_color *dscp_table,
690                                struct rte_mtr_error *error)
691 {
692         enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRE_COLOR_MAX];
693         enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
694                                               ROC_NIX_BPF_COLOR_YELLOW,
695                                               ROC_NIX_BPF_COLOR_RED};
696         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
697         struct roc_nix_bpf_precolor table;
698         struct roc_nix *nix = &dev->nix;
699         struct cnxk_meter_node *mtr;
700         int rc, i;
701
702         mtr = nix_mtr_find(dev, mtr_id);
703         if (mtr == NULL) {
704                 return -rte_mtr_error_set(error, ENOENT,
705                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
706                                           "Meter object not found");
707         }
708
709         if (!dscp_table) {
710                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
711                         nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
712         } else {
713                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
714                         nix_dscp_tbl[i] = color_map[dscp_table[i]];
715         }
716
717         table.count = ROC_NIX_BPF_PRE_COLOR_MAX;
718         table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
719         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
720                 table.color[i] = nix_dscp_tbl[i];
721
722         rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
723                                              lvl_map[mtr->level], &table);
724         if (rc) {
725                 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
726                                   NULL, NULL);
727                 goto exit;
728         }
729
730         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
731                 dev->precolor_tbl[i] = nix_dscp_tbl[i];
732
733 exit:
734         return rc;
735 }
736
737 static int
738 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
739                           uint64_t stats_mask, struct rte_mtr_error *error)
740 {
741         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
742         struct cnxk_meter_node *mtr;
743
744         if (!stats_mask)
745                 return -rte_mtr_error_set(error, EINVAL,
746                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
747                                           "no bit is set to stats mask");
748
749         mtr = nix_mtr_find(dev, mtr_id);
750         if (mtr == NULL) {
751                 return -rte_mtr_error_set(error, ENOENT,
752                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
753                                           "Meter object not found");
754         }
755
756         mtr->params.stats_mask = stats_mask;
757         return 0;
758 }
759
760 static int
761 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
762                         struct rte_mtr_stats *stats, uint64_t *stats_mask,
763                         int clear, struct rte_mtr_error *error)
764 {
765         uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
766         uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
767         uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
768         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
769         uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
770         uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
771         uint64_t mask = NIX_BPF_STATS_MASK_ALL;
772         struct roc_nix *nix = &dev->nix;
773         struct cnxk_meter_node *mtr;
774         int rc;
775
776         if (!stats)
777                 return -rte_mtr_error_set(error, EINVAL,
778                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
779                                           "stats pointer is NULL");
780
781         mtr = nix_mtr_find(dev, mtr_id);
782         if (mtr == NULL) {
783                 return -rte_mtr_error_set(error, ENOENT,
784                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
785                                           "Meter object not found");
786         }
787
788         rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
789                                     bpf_stats);
790         if (rc) {
791                 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
792                                   NULL, NULL);
793                 goto exit;
794         }
795
796         green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
797         green_octs_pass =
798                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
799         green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
800         green_octs_drop =
801                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
802         yellow_pkt_pass =
803                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
804         yellow_octs_pass =
805                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
806         yellow_pkt_drop =
807                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
808         yellow_octs_drop =
809                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
810         red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
811         red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
812         red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
813         red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
814
815         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
816                 stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
817
818         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
819                 stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
820
821         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
822                 stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
823
824         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
825                 stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
826
827         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
828                 stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
829
830         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
831                 stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
832
833         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
834                 stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
835                                         bpf_stats[yellow_pkt_drop] +
836                                         bpf_stats[red_pkt_drop];
837
838         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
839                 stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
840                                          bpf_stats[yellow_octs_drop] +
841                                          bpf_stats[red_octs_drop];
842
843         if (stats_mask)
844                 *stats_mask = mtr->params.stats_mask;
845
846         if (clear) {
847                 rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
848                                              lvl_map[mtr->level]);
849                 if (rc) {
850                         rte_mtr_error_set(error, rc,
851                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
852                                           NULL);
853                         goto exit;
854                 }
855         }
856
857 exit:
858         return rc;
859 }
860
861 const struct rte_mtr_ops nix_mtr_ops = {
862         .capabilities_get = cnxk_nix_mtr_capabilities_get,
863         .meter_profile_add = cnxk_nix_mtr_profile_add,
864         .meter_profile_delete = cnxk_nix_mtr_profile_delete,
865         .meter_policy_validate = cnxk_nix_mtr_policy_validate,
866         .meter_policy_add = cnxk_nix_mtr_policy_add,
867         .meter_policy_delete = cnxk_nix_mtr_policy_delete,
868         .create = cnxk_nix_mtr_create,
869         .destroy = cnxk_nix_mtr_destroy,
870         .meter_enable = cnxk_nix_mtr_enable,
871         .meter_disable = cnxk_nix_mtr_disable,
872         .meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
873         .stats_update = cnxk_nix_mtr_stats_update,
874         .stats_read = cnxk_nix_mtr_stats_read,
875 };
876
877 int
878 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
879 {
880         RTE_SET_USED(dev);
881
882         *(const void **)ops = &nix_mtr_ops;
883         return 0;
884 }
885
886 int
887 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
888 {
889         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
890         struct cnxk_mtr_profile_node *profile;
891         struct cnxk_mtr_policy_node *policy;
892         struct cnxk_meter_node *mtr;
893
894         mtr = nix_mtr_find(dev, id);
895         if (mtr == NULL)
896                 return -EINVAL;
897
898         profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
899         if (profile == NULL)
900                 return -EINVAL;
901
902         policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
903         if (policy == NULL)
904                 return -EINVAL;
905
906         return 0;
907 }
908
909 int
910 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
911                        struct cnxk_mtr_policy_node **policy_act)
912 {
913         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
914         struct cnxk_mtr_policy_node *policy;
915         struct cnxk_meter_node *mtr;
916
917         mtr = nix_mtr_find(dev, id);
918         if (mtr == NULL)
919                 return -EINVAL;
920
921         policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
922         if (policy == NULL)
923                 return -EINVAL;
924
925         *policy_act = policy;
926
927         return 0;
928 }
929
930 int
931 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
932                   const uint16_t *queue)
933 {
934         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
935         struct cnxk_meter_node *mtr;
936         uint32_t i;
937
938         mtr = nix_mtr_find(dev, id);
939         if (mtr == NULL)
940                 return -EINVAL;
941
942         mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
943         if (mtr->rq_id == NULL)
944                 return -ENOMEM;
945
946         mtr->rq_num = queue_num;
947         for (i = 0; i < queue_num; i++)
948                 mtr->rq_id[i] = queue[i];
949
950         return 0;
951 }
952
953 int
954 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
955 {
956         struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
957         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
958         uint32_t mtr_id = cur_id;
959         int i = 0, j = 0;
960
961         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
962                 mtr[i] = nix_mtr_find(dev, mtr_id);
963                 if (mtr[i])
964                         mtr_id = mtr[i]->next_id;
965         }
966         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
967                 if (mtr[i]) {
968                         for (j = 0; j < MAX_PRV_MTR_NODES; j++)
969                                 mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
970                         mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
971                         mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
972                         mtr[i]->is_next = false;
973                         mtr[i]->prev_cnt = 0;
974                 }
975         }
976         return 0;
977 }
978
979 int
980 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
981                      uint32_t prev_id, uint32_t next_id)
982 {
983         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
984         struct cnxk_meter_node *mtr;
985
986         mtr = nix_mtr_find(dev, cur_id);
987         if (mtr == NULL)
988                 return -EINVAL;
989
990         switch (lvl_map[mtr->level]) {
991         case ROC_NIX_BPF_LEVEL_F_LEAF:
992                 mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
993                 mtr->next_id = next_id;
994                 mtr->is_next = true;
995                 break;
996         case ROC_NIX_BPF_LEVEL_F_MID:
997                 mtr->prev_id[mtr->prev_cnt] = prev_id;
998                 mtr->next_id = next_id;
999                 mtr->is_next = true;
1000                 break;
1001         case ROC_NIX_BPF_LEVEL_F_TOP:
1002                 mtr->prev_id[mtr->prev_cnt] = prev_id;
1003                 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
1004                 mtr->is_next = false;
1005                 break;
1006         default:
1007                 plt_err("Invalid meter level");
1008                 return -EINVAL;
1009         }
1010
1011         return 0;
1012 }
1013
1014 struct cnxk_meter_node *
1015 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
1016 {
1017         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1018         struct cnxk_meter_node *mtr;
1019
1020         mtr = nix_mtr_find(dev, id);
1021         if (mtr == NULL)
1022                 return NULL;
1023
1024         return mtr;
1025 }
1026
1027 int
1028 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
1029 {
1030         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1031         struct cnxk_meter_node *mtr;
1032
1033         mtr = nix_mtr_find(dev, id);
1034         if (mtr == NULL)
1035                 return -EINVAL;
1036
1037         mtr->level = level;
1038         return 0;
1039 }
1040
1041 static void
1042 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1043 {
1044         enum roc_nix_bpf_algo alg_map[] = {
1045                 ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
1046                 ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
1047         struct cnxk_mtr_profile_node *profile = mtr->profile;
1048         struct cnxk_mtr_policy_node *policy = mtr->policy;
1049
1050         cfg->alg = alg_map[profile->profile.alg];
1051         cfg->lmode = profile->profile.packet_mode;
1052
1053         switch (cfg->alg) {
1054         case ROC_NIX_BPF_ALGO_2697:
1055                 cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1056                 cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1057                 cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1058                 break;
1059         case ROC_NIX_BPF_ALGO_2698:
1060                 cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1061                 cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1062                 cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1063                 cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1064                 break;
1065         case ROC_NIX_BPF_ALGO_4115:
1066                 cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1067                 cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1068                 cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1069                 cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1070                 break;
1071         default:
1072                 break;
1073         }
1074
1075         cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1076         cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1077         cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1078
1079         if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1080             RTE_FLOW_ACTION_TYPE_DROP)
1081                 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1082
1083         if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1084             RTE_FLOW_ACTION_TYPE_DROP)
1085                 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1086
1087         if (policy->actions[RTE_COLOR_RED].action_fate ==
1088             RTE_FLOW_ACTION_TYPE_DROP)
1089                 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1090 }
1091
1092 static void
1093 nix_dscp_table_map(struct cnxk_meter_node *mtr,
1094                    struct roc_nix_bpf_precolor *tbl)
1095 {
1096         enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1097                                               ROC_NIX_BPF_COLOR_YELLOW,
1098                                               ROC_NIX_BPF_COLOR_RED};
1099         int i;
1100
1101         tbl->count = ROC_NIX_BPF_PRE_COLOR_MAX;
1102         tbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1103
1104         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1105                 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1106
1107         if (mtr->params.dscp_table) {
1108                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1109                         tbl->color[i] = color_map[mtr->params.dscp_table[i]];
1110         }
1111 }
1112
1113 int
1114 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1115                 struct rte_mtr_error *error)
1116 {
1117         return cnxk_nix_mtr_destroy(eth_dev, id, error);
1118 }
1119
1120 int
1121 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1122 {
1123         enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1124         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1125         struct cnxk_meter_node *base_mtr, *next_mtr;
1126         struct roc_nix *nix = &dev->nix;
1127         uint32_t cur_mtr_id = id;
1128         int rc, i;
1129
1130         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1131                 base_mtr = nix_mtr_find(dev, cur_mtr_id);
1132                 if (base_mtr) {
1133                         lvl_flag = lvl_map[base_mtr->level];
1134                         if (base_mtr->is_next) {
1135                                 next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1136                                 if (next_mtr) {
1137                                         if (!base_mtr->is_used) {
1138                                                 rc = roc_nix_bpf_connect(nix,
1139                                                         lvl_flag,
1140                                                         base_mtr->bpf_id,
1141                                                         next_mtr->bpf_id);
1142                                                 if (rc)
1143                                                         return rc;
1144                                         }
1145                                 }
1146                                 cur_mtr_id = base_mtr->next_id;
1147                         }
1148                 }
1149         }
1150         return 0;
1151 }
1152
1153 int
1154 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1155 {
1156         struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1157         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1158         struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1159         uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1160         uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1161         uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1162         uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1163         int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1164         struct roc_nix *nix = &dev->nix;
1165         struct roc_nix_bpf_precolor tbl;
1166         struct roc_nix_bpf_cfg cfg;
1167         struct roc_nix_rq *rq;
1168         uint8_t lvl_mask;
1169         uint32_t i;
1170         uint32_t j;
1171         int rc;
1172
1173         mtr[0] = nix_mtr_find(dev, id);
1174         if (mtr[0] == NULL)
1175                 return -EINVAL;
1176
1177         num_mtr[0] = 1;
1178         idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1179         if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1180                 return -EINVAL;
1181
1182         lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1183         if (mtr[0]->is_used)
1184                 per_lvl_cnt[idx0] = 0;
1185         else
1186                 per_lvl_cnt[idx0] = 1;
1187
1188         if (mtr[0]->is_next) {
1189                 mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1190                 if (mtr[1] == NULL)
1191                         return -EINVAL;
1192                 num_mtr[1] = 1;
1193                 idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1194                 if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1195                         return -EINVAL;
1196
1197                 lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1198                 if (mtr[1]->is_used)
1199                         per_lvl_cnt[idx1] = 0;
1200                 else
1201                         per_lvl_cnt[idx1] = 1;
1202         }
1203
1204         if (mtr[1] && mtr[1]->is_next) {
1205                 mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1206                 if (mtr[2] == NULL)
1207                         return -EINVAL;
1208
1209                 num_mtr[2] = 1;
1210                 idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1211                 if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1212                         return -EINVAL;
1213
1214                 lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1215                 if (mtr[2]->is_used)
1216                         per_lvl_cnt[idx2] = 0;
1217                 else
1218                         per_lvl_cnt[idx2] = 1;
1219         }
1220
1221         rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1222         if (rc)
1223                 return rc;
1224         if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1225                 mtr[0]->bpf_id = profs[idx0].ids[0];
1226
1227         if (num_mtr[0])
1228                 if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1229                         if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1230                                 mtr[1]->bpf_id = profs[idx1].ids[0];
1231
1232         if (num_mtr[1])
1233                 if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1234                         if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1235                                 mtr[2]->bpf_id = profs[idx2].ids[0];
1236
1237         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1238                 if (num_mtr[i]) {
1239                         if (!mtr[i]->is_used) {
1240                                 memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1241                                 nix_mtr_config_map(mtr[i], &cfg);
1242                                 rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1243                                                         lvl_map[mtr[i]->level],
1244                                                         &cfg);
1245
1246                                 memset(&tbl, 0,
1247                                        sizeof(struct roc_nix_bpf_precolor));
1248                                 nix_dscp_table_map(mtr[i], &tbl);
1249                                 rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1250                                         mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1251                                         &tbl);
1252
1253                                 if (mtr[i]->params.meter_enable) {
1254                                         for (j = 0; j < mtr[i]->rq_num; j++) {
1255                                                 rq = &dev->rqs[mtr[i]->rq_id
1256                                                                        [j]];
1257                                                 rc = roc_nix_bpf_ena_dis(nix,
1258                                                         mtr[i]->bpf_id, rq,
1259                                                         true);
1260                                         }
1261                                 }
1262                         }
1263                 }
1264         }
1265
1266         return rc;
1267 }
1268
1269 int
1270 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1271                               uint32_t *prev_id, uint32_t *next_id,
1272                               struct cnxk_mtr_policy_node *policy,
1273                               int *tree_level)
1274 {
1275         uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1276         uint32_t action_fate_green =
1277                 policy->actions[RTE_COLOR_GREEN].action_fate;
1278         uint32_t action_fate_yellow =
1279                 policy->actions[RTE_COLOR_YELLOW].action_fate;
1280         uint32_t cur_mtr_id = *next_id;
1281         uint32_t next_mtr_id = 0xffff;
1282         uint32_t prev_mtr_id = 0xffff;
1283         struct cnxk_meter_node *mtr;
1284
1285         if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1286                 next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1287
1288         if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1289                 next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1290
1291         if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1292                 next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1293
1294         if (next_mtr_id != 0xffff) {
1295                 switch (*tree_level) {
1296                 case 0:
1297                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1298                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1299                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1300                                 nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1301                                                      next_mtr_id);
1302                         } else {
1303                                 if (mtr->level == 0)
1304                                         mtr->is_used = true;
1305                                 else
1306                                         return -EINVAL;
1307                         }
1308                         (*tree_level)++;
1309                         *next_id = next_mtr_id;
1310                         break;
1311                 case 1:
1312                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1313                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1314                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1315                                 prev_mtr_id = id;
1316                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1317                                                      prev_mtr_id, next_mtr_id);
1318                         } else {
1319                                 if (mtr->level == 1) {
1320                                         mtr->prev_cnt++;
1321                                         prev_mtr_id = id;
1322                                         nix_mtr_chain_update(eth_dev,
1323                                                 cur_mtr_id, prev_mtr_id,
1324                                                 next_mtr_id);
1325
1326                                         mtr->is_used = true;
1327                                 } else {
1328                                         return -EINVAL;
1329                                 }
1330                         }
1331                         (*tree_level)++;
1332                         *next_id = next_mtr_id;
1333                         *prev_id = cur_mtr_id;
1334                         break;
1335                 case 2:
1336                         nix_mtr_chain_reset(eth_dev, id);
1337                         return -EINVAL;
1338                 }
1339         } else {
1340                 switch (*tree_level) {
1341                 case 0:
1342                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1343                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1344                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1345                         } else {
1346                                 if (mtr->level == 0)
1347                                         mtr->is_used = true;
1348                                 else
1349                                         return -EINVAL;
1350                         }
1351                         break;
1352                 case 1:
1353                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1354                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1355                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1356                                 prev_mtr_id = id;
1357                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1358                                                      prev_mtr_id, -1);
1359                         } else {
1360                                 if (mtr->level == 1) {
1361                                         mtr->prev_cnt++;
1362                                         prev_mtr_id = id;
1363                                         nix_mtr_chain_update(eth_dev,
1364                                                              cur_mtr_id,
1365                                                              prev_mtr_id, -1);
1366                                         mtr->is_used = true;
1367                                 } else {
1368                                         return -EINVAL;
1369                                 }
1370                         }
1371                         break;
1372                 case 2:
1373                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1374                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1375                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1376                                 prev_mtr_id = *prev_id;
1377                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1378                                                      prev_mtr_id, -1);
1379                         } else {
1380                                 if (mtr->level == 2) {
1381                                         mtr->prev_cnt++;
1382                                         prev_mtr_id = *prev_id;
1383                                         nix_mtr_chain_update(eth_dev,
1384                                                              cur_mtr_id,
1385                                                              prev_mtr_id, -1);
1386                                         mtr->is_used = true;
1387                                 } else {
1388                                         return -EINVAL;
1389                                 }
1390                         }
1391                         break;
1392                 }
1393                 *next_id = 0xffff;
1394         }
1395
1396         return 0;
1397 }
1398
1399 int
1400 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev)
1401 {
1402         struct rte_mtr_capabilities capa;
1403         struct rte_mtr_error error;
1404
1405         return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1406 }