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