net/mlx5: add C++ include guard to public header
[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 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
290                              struct rte_mtr_meter_policy_params *policy,
291                              struct rte_mtr_error *error)
292 {
293         static const char *const action_color[] = {"Green", "Yellow", "Red"};
294         bool supported[RTE_COLORS] = {false, false, false};
295         const struct rte_flow_action *action;
296         char message[1024];
297         uint32_t i;
298
299         RTE_SET_USED(dev);
300
301         if (!policy)
302                 return 0; /* Nothing to be validated */
303
304         for (i = 0; i < RTE_COLORS; i++) {
305                 if (policy->actions[i]) {
306                         for (action = policy->actions[i];
307                              action->type != RTE_FLOW_ACTION_TYPE_END;
308                              action++) {
309                                 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
310                                         supported[i] = true;
311
312                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
313                                         supported[i] = true;
314
315                                 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
316                                         supported[i] = true;
317
318                                 if (!supported[i]) {
319                                         sprintf(message,
320                                                 "%s action is not valid",
321                                                 action_color[i]);
322                                         return -rte_mtr_error_set(error,
323                                           ENOTSUP,
324                                           RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
325                                           message);
326                                 }
327                         }
328                 } else {
329                         sprintf(message, "%s action is null", action_color[i]);
330                         return -rte_mtr_error_set(error, EINVAL,
331                                 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
332                                 message);
333                 }
334         }
335
336         return 0;
337 }
338
339 static void
340 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
341                          struct rte_mtr_meter_policy_params *policy)
342
343 {
344         const struct rte_flow_action_meter *mtr;
345         const struct rte_flow_action *action;
346         int i;
347
348         for (i = 0; i < RTE_COLORS; i++) {
349                 if (policy->actions[i]) {
350                         for (action = policy->actions[i];
351                              action->type != RTE_FLOW_ACTION_TYPE_END;
352                              action++) {
353                                 if (action->type ==
354                                     RTE_FLOW_ACTION_TYPE_METER) {
355                                         fmp->actions[i].action_fate =
356                                                 action->type;
357                                         mtr = (const struct
358                                                rte_flow_action_meter *)
359                                                       action->conf;
360                                         fmp->actions[i].mtr_id = mtr->mtr_id;
361                                 }
362
363                                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
364                                         fmp->actions[i].action_fate =
365                                                 action->type;
366                                 }
367                         }
368                 }
369         }
370 }
371
372 static int
373 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
374                         struct rte_mtr_meter_policy_params *policy,
375                         struct rte_mtr_error *error)
376 {
377         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
378         struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
379         struct cnxk_mtr_policy_node *fmp;
380         int rc;
381
382         fmp = nix_mtr_policy_find(dev, policy_id);
383         if (fmp) {
384                 return -rte_mtr_error_set(error, EEXIST,
385                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
386                                           NULL, "Policy already exist");
387         }
388
389         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
390         if (fmp == NULL) {
391                 return -rte_mtr_error_set(error, ENOMEM,
392                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
393                                           "Memory allocation failure");
394         } else {
395                 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
396                 if (rc)
397                         goto exit;
398         }
399
400         fmp->id = policy_id;
401         cnxk_fill_policy_actions(fmp, policy);
402         TAILQ_INSERT_TAIL(fmps, fmp, next);
403         return 0;
404
405 exit:
406         plt_free(fmp);
407         return rc;
408 }
409
410 static int
411 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
412                            struct rte_mtr_error *error)
413 {
414         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
415         struct cnxk_mtr_policy_node *fmp;
416
417         fmp = nix_mtr_policy_find(dev, policy_id);
418         if (fmp == NULL) {
419                 return -rte_mtr_error_set(error, ENOENT,
420                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
421                                           NULL, "No policy found");
422         }
423
424         if (fmp->ref_cnt)
425                 return -rte_mtr_error_set(error, EBUSY,
426                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
427                                           NULL, "Meter policy is in use.");
428
429         TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
430         plt_free(fmp);
431
432         return 0;
433 }
434
435 static int
436 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
437                     struct rte_mtr_params *params, int shared,
438                     struct rte_mtr_error *error)
439 {
440         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
441         struct cnxk_mtr_profile_node *profile;
442         struct cnxk_mtr_policy_node *policy;
443         struct cnxk_mtr *fm = &dev->mtr;
444         struct cnxk_meter_node *mtr;
445         int i;
446
447         RTE_SET_USED(shared);
448
449         if (params == NULL)
450                 return -rte_mtr_error_set(error, ENOENT,
451                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
452                                           "Meter params are invalid.");
453
454         profile = nix_mtr_profile_find(dev, params->meter_profile_id);
455         if (profile == NULL)
456                 return -rte_mtr_error_set(error, ENOENT,
457                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
458                                           &params->meter_profile_id,
459                                           "Meter profile is invalid.");
460
461         policy = nix_mtr_policy_find(dev, params->meter_policy_id);
462         if (policy == NULL)
463                 return -rte_mtr_error_set(error, ENOENT,
464                                           RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
465                                           &params->meter_policy_id,
466                                           "Meter policy is invalid.");
467
468         mtr = nix_mtr_find(dev, mtr_id);
469         if (mtr) {
470                 return -rte_mtr_error_set(error, EEXIST,
471                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
472                                           "Meter already exist");
473         }
474
475         mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
476         if (mtr == NULL) {
477                 return -rte_mtr_error_set(error, ENOMEM,
478                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
479                                           "Meter memory alloc failed.");
480         }
481
482         mtr->id = mtr_id;
483         mtr->profile = profile;
484         mtr->policy = policy;
485         mtr->params = *params;
486         mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
487         mtr->prev_cnt = 0;
488         for (i = 0; i < MAX_PRV_MTR_NODES; i++)
489                 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
490
491         mtr->next_id = ROC_NIX_BPF_ID_INVALID;
492         mtr->is_next = false;
493         mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
494
495         if (params->dscp_table) {
496                 mtr->params.dscp_table =
497                         plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN);
498                 if (mtr->params.dscp_table == NULL) {
499                         plt_free(mtr);
500                         return -rte_mtr_error_set(error, ENOMEM,
501                                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
502                                         NULL, "Memory alloc failed.");
503                 }
504
505                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
506                         mtr->params.dscp_table[i] = params->dscp_table[i];
507         }
508
509         profile->ref_cnt++;
510         policy->ref_cnt++;
511         TAILQ_INSERT_TAIL(fm, mtr, next);
512         return 0;
513 }
514
515 static int
516 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
517                      struct rte_mtr_error *error)
518 {
519         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
520         struct roc_nix_bpf_objs profs = {0};
521         struct cnxk_mtr *fm = &dev->mtr;
522         struct roc_nix *nix = &dev->nix;
523         struct cnxk_meter_node *mtr;
524         struct cnxk_meter_node *mid_mtr;
525         struct cnxk_meter_node *top_mtr;
526         int rc = 0;
527
528         mtr = nix_mtr_find(dev, mtr_id);
529         if (mtr == NULL) {
530                 return -rte_mtr_error_set(error, ENOENT,
531                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
532                                           "Meter id is invalid.");
533         }
534
535         if (mtr->ref_cnt) {
536                 return -rte_mtr_error_set(error, EADDRINUSE,
537                                           RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
538                                           "Meter id in use.");
539         }
540
541         switch (lvl_map[mtr->level]) {
542         case ROC_NIX_BPF_LEVEL_F_LEAF:
543                 if (mtr->is_next) {
544                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
545                                                  mtr->bpf_id,
546                                                  ROC_NIX_BPF_ID_INVALID);
547                 }
548                 break;
549         case ROC_NIX_BPF_LEVEL_F_MID:
550                 while ((mtr->prev_cnt) + 1) {
551                         mid_mtr =
552                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
553                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
554                                                  mid_mtr->bpf_id,
555                                                  ROC_NIX_BPF_ID_INVALID);
556                         mtr->prev_cnt--;
557                 }
558                 if (mtr->is_next) {
559                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
560                                                  mtr->bpf_id,
561                                                  ROC_NIX_BPF_ID_INVALID);
562                 }
563                 break;
564         case ROC_NIX_BPF_LEVEL_F_TOP:
565                 while (mtr->prev_cnt) {
566                         top_mtr =
567                                 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
568                         rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
569                                                  top_mtr->bpf_id,
570                                                  ROC_NIX_BPF_ID_INVALID);
571                         mtr->prev_cnt--;
572                 }
573                 break;
574         default:
575                 return -rte_mtr_error_set(error, EINVAL,
576                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
577                                           "Invalid meter level");
578         }
579
580         if (rc)
581                 goto exit;
582
583         profs.level = mtr->level;
584         profs.count = 1;
585         profs.ids[0] = mtr->bpf_id;
586         rc = roc_nix_bpf_free(nix, &profs, 1);
587         if (rc)
588                 goto exit;
589
590         mtr->policy->ref_cnt--;
591         mtr->profile->ref_cnt--;
592         TAILQ_REMOVE(fm, mtr, next);
593         plt_free(mtr->params.dscp_table);
594         plt_free(mtr);
595
596 exit:
597         return rc;
598 }
599
600 static int
601 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
602                     struct rte_mtr_error *error)
603 {
604         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
605         struct roc_nix *nix = &dev->nix;
606         struct cnxk_meter_node *mtr;
607         struct roc_nix_rq *rq;
608         uint32_t i;
609         int rc = 0;
610
611         mtr = nix_mtr_find(dev, mtr_id);
612         if (mtr == NULL) {
613                 return -rte_mtr_error_set(error, ENOENT,
614                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
615                                           "Meter id is invalid.");
616         }
617
618         if (mtr->level != 0)
619                 return 0;
620
621         for (i = 0; i < mtr->rq_num; i++) {
622                 rq = &dev->rqs[mtr->rq_id[i]];
623                 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
624         }
625
626         return rc;
627 }
628
629 static int
630 cnxk_nix_mtr_disable(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, false);
653         }
654
655         return rc;
656 }
657
658 static int
659 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
660                                enum rte_color *dscp_table,
661                                struct rte_mtr_error *error)
662 {
663         enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRE_COLOR_MAX];
664         enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
665                                               ROC_NIX_BPF_COLOR_YELLOW,
666                                               ROC_NIX_BPF_COLOR_RED};
667         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
668         struct roc_nix_bpf_precolor table;
669         struct roc_nix *nix = &dev->nix;
670         struct cnxk_meter_node *mtr;
671         int rc, i;
672
673         mtr = nix_mtr_find(dev, mtr_id);
674         if (mtr == NULL) {
675                 return -rte_mtr_error_set(error, ENOENT,
676                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
677                                           "Meter object not found");
678         }
679
680         if (!dscp_table) {
681                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
682                         nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
683         } else {
684                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
685                         nix_dscp_tbl[i] = color_map[dscp_table[i]];
686         }
687
688         table.count = ROC_NIX_BPF_PRE_COLOR_MAX;
689         table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
690         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
691                 table.color[i] = nix_dscp_tbl[i];
692
693         rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
694                                              lvl_map[mtr->level], &table);
695         if (rc) {
696                 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
697                                   NULL, NULL);
698                 goto exit;
699         }
700
701         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
702                 dev->precolor_tbl[i] = nix_dscp_tbl[i];
703
704 exit:
705         return rc;
706 }
707
708 static int
709 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
710                           uint64_t stats_mask, struct rte_mtr_error *error)
711 {
712         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
713         struct cnxk_meter_node *mtr;
714
715         if (!stats_mask)
716                 return -rte_mtr_error_set(error, EINVAL,
717                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
718                                           "no bit is set to stats mask");
719
720         mtr = nix_mtr_find(dev, mtr_id);
721         if (mtr == NULL) {
722                 return -rte_mtr_error_set(error, ENOENT,
723                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
724                                           "Meter object not found");
725         }
726
727         mtr->params.stats_mask = stats_mask;
728         return 0;
729 }
730
731 static int
732 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
733                         struct rte_mtr_stats *stats, uint64_t *stats_mask,
734                         int clear, struct rte_mtr_error *error)
735 {
736         uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
737         uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
738         uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
739         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
740         uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
741         uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
742         uint64_t mask = NIX_BPF_STATS_MASK_ALL;
743         struct roc_nix *nix = &dev->nix;
744         struct cnxk_meter_node *mtr;
745         int rc;
746
747         if (!stats)
748                 return -rte_mtr_error_set(error, EINVAL,
749                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
750                                           "stats pointer is NULL");
751
752         mtr = nix_mtr_find(dev, mtr_id);
753         if (mtr == NULL) {
754                 return -rte_mtr_error_set(error, ENOENT,
755                                           RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
756                                           "Meter object not found");
757         }
758
759         rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
760                                     bpf_stats);
761         if (rc) {
762                 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
763                                   NULL, NULL);
764                 goto exit;
765         }
766
767         green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
768         green_octs_pass =
769                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
770         green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
771         green_octs_drop =
772                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
773         yellow_pkt_pass =
774                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
775         yellow_octs_pass =
776                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
777         yellow_pkt_drop =
778                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
779         yellow_octs_drop =
780                 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
781         red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
782         red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
783         red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
784         red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
785
786         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
787                 stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
788
789         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
790                 stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
791
792         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
793                 stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
794
795         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
796                 stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
797
798         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
799                 stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
800
801         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
802                 stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
803
804         if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
805                 stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
806                                         bpf_stats[yellow_pkt_drop] +
807                                         bpf_stats[red_pkt_drop];
808
809         if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
810                 stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
811                                          bpf_stats[yellow_octs_drop] +
812                                          bpf_stats[red_octs_drop];
813
814         if (stats_mask)
815                 *stats_mask = mtr->params.stats_mask;
816
817         if (clear) {
818                 rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
819                                              lvl_map[mtr->level]);
820                 if (rc) {
821                         rte_mtr_error_set(error, rc,
822                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
823                                           NULL);
824                         goto exit;
825                 }
826         }
827
828 exit:
829         return rc;
830 }
831
832 const struct rte_mtr_ops nix_mtr_ops = {
833         .capabilities_get = cnxk_nix_mtr_capabilities_get,
834         .meter_profile_add = cnxk_nix_mtr_profile_add,
835         .meter_profile_delete = cnxk_nix_mtr_profile_delete,
836         .meter_policy_validate = cnxk_nix_mtr_policy_validate,
837         .meter_policy_add = cnxk_nix_mtr_policy_add,
838         .meter_policy_delete = cnxk_nix_mtr_policy_delete,
839         .create = cnxk_nix_mtr_create,
840         .destroy = cnxk_nix_mtr_destroy,
841         .meter_enable = cnxk_nix_mtr_enable,
842         .meter_disable = cnxk_nix_mtr_disable,
843         .meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
844         .stats_update = cnxk_nix_mtr_stats_update,
845         .stats_read = cnxk_nix_mtr_stats_read,
846 };
847
848 int
849 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
850 {
851         RTE_SET_USED(dev);
852
853         *(const void **)ops = &nix_mtr_ops;
854         return 0;
855 }
856
857 int
858 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
859 {
860         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
861         struct cnxk_mtr_profile_node *profile;
862         struct cnxk_mtr_policy_node *policy;
863         struct cnxk_meter_node *mtr;
864
865         mtr = nix_mtr_find(dev, id);
866         if (mtr == NULL)
867                 return -EINVAL;
868
869         profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
870         if (profile == NULL)
871                 return -EINVAL;
872
873         policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
874         if (policy == NULL)
875                 return -EINVAL;
876
877         return 0;
878 }
879
880 int
881 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
882                        struct cnxk_mtr_policy_node **policy_act)
883 {
884         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
885         struct cnxk_mtr_policy_node *policy;
886         struct cnxk_meter_node *mtr;
887
888         mtr = nix_mtr_find(dev, id);
889         if (mtr == NULL)
890                 return -EINVAL;
891
892         policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
893         if (policy == NULL)
894                 return -EINVAL;
895
896         *policy_act = policy;
897
898         return 0;
899 }
900
901 int
902 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
903                   const uint16_t *queue)
904 {
905         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
906         struct cnxk_meter_node *mtr;
907         uint32_t i;
908
909         mtr = nix_mtr_find(dev, id);
910         if (mtr == NULL)
911                 return -EINVAL;
912
913         mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
914         if (mtr->rq_id == NULL)
915                 return -ENOMEM;
916
917         mtr->rq_num = queue_num;
918         for (i = 0; i < queue_num; i++)
919                 mtr->rq_id[i] = queue[i];
920
921         return 0;
922 }
923
924 int
925 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
926 {
927         struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
928         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
929         uint32_t mtr_id = cur_id;
930         int i = 0, j = 0;
931
932         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
933                 mtr[i] = nix_mtr_find(dev, mtr_id);
934                 if (mtr[i])
935                         mtr_id = mtr[i]->next_id;
936         }
937         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
938                 if (mtr[i]) {
939                         for (j = 0; j < MAX_PRV_MTR_NODES; j++)
940                                 mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
941                         mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
942                         mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
943                         mtr[i]->is_next = false;
944                         mtr[i]->prev_cnt = 0;
945                 }
946         }
947         return 0;
948 }
949
950 int
951 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
952                      uint32_t prev_id, uint32_t next_id)
953 {
954         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
955         struct cnxk_meter_node *mtr;
956
957         mtr = nix_mtr_find(dev, cur_id);
958         if (mtr == NULL)
959                 return -EINVAL;
960
961         switch (lvl_map[mtr->level]) {
962         case ROC_NIX_BPF_LEVEL_F_LEAF:
963                 mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
964                 mtr->next_id = next_id;
965                 mtr->is_next = true;
966                 break;
967         case ROC_NIX_BPF_LEVEL_F_MID:
968                 mtr->prev_id[mtr->prev_cnt] = prev_id;
969                 mtr->next_id = next_id;
970                 mtr->is_next = true;
971                 break;
972         case ROC_NIX_BPF_LEVEL_F_TOP:
973                 mtr->prev_id[mtr->prev_cnt] = prev_id;
974                 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
975                 mtr->is_next = false;
976                 break;
977         default:
978                 plt_err("Invalid meter level");
979                 return -EINVAL;
980         }
981
982         return 0;
983 }
984
985 struct cnxk_meter_node *
986 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
987 {
988         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
989         struct cnxk_meter_node *mtr;
990
991         mtr = nix_mtr_find(dev, id);
992         if (mtr == NULL)
993                 return NULL;
994
995         return mtr;
996 }
997
998 int
999 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
1000 {
1001         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1002         struct cnxk_meter_node *mtr;
1003
1004         mtr = nix_mtr_find(dev, id);
1005         if (mtr == NULL)
1006                 return -EINVAL;
1007
1008         mtr->level = level;
1009         return 0;
1010 }
1011
1012 static void
1013 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1014 {
1015         enum roc_nix_bpf_algo alg_map[] = {
1016                 ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
1017                 ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
1018         struct cnxk_mtr_profile_node *profile = mtr->profile;
1019         struct cnxk_mtr_policy_node *policy = mtr->policy;
1020
1021         cfg->alg = alg_map[profile->profile.alg];
1022         cfg->lmode = profile->profile.packet_mode;
1023
1024         switch (cfg->alg) {
1025         case ROC_NIX_BPF_ALGO_2697:
1026                 cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1027                 cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1028                 cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1029                 break;
1030         case ROC_NIX_BPF_ALGO_2698:
1031                 cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1032                 cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1033                 cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1034                 cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1035                 break;
1036         case ROC_NIX_BPF_ALGO_4115:
1037                 cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1038                 cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1039                 cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1040                 cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1041                 break;
1042         default:
1043                 break;
1044         }
1045
1046         cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1047         cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1048         cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1049
1050         if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1051             RTE_FLOW_ACTION_TYPE_DROP)
1052                 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1053
1054         if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1055             RTE_FLOW_ACTION_TYPE_DROP)
1056                 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1057
1058         if (policy->actions[RTE_COLOR_RED].action_fate ==
1059             RTE_FLOW_ACTION_TYPE_DROP)
1060                 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1061 }
1062
1063 static void
1064 nix_dscp_table_map(struct cnxk_meter_node *mtr,
1065                    struct roc_nix_bpf_precolor *tbl)
1066 {
1067         enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1068                                               ROC_NIX_BPF_COLOR_YELLOW,
1069                                               ROC_NIX_BPF_COLOR_RED};
1070         int i;
1071
1072         tbl->count = ROC_NIX_BPF_PRE_COLOR_MAX;
1073         tbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1074
1075         for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1076                 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1077
1078         if (mtr->params.dscp_table) {
1079                 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1080                         tbl->color[i] = color_map[mtr->params.dscp_table[i]];
1081         }
1082 }
1083
1084 int
1085 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1086                 struct rte_mtr_error *error)
1087 {
1088         return cnxk_nix_mtr_destroy(eth_dev, id, error);
1089 }
1090
1091 int
1092 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1093 {
1094         enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1095         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1096         struct cnxk_meter_node *base_mtr, *next_mtr;
1097         struct roc_nix *nix = &dev->nix;
1098         uint32_t cur_mtr_id = id;
1099         int rc, i;
1100
1101         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1102                 base_mtr = nix_mtr_find(dev, cur_mtr_id);
1103                 if (base_mtr) {
1104                         lvl_flag = lvl_map[base_mtr->level];
1105                         if (base_mtr->is_next) {
1106                                 next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1107                                 if (next_mtr) {
1108                                         if (!base_mtr->is_used) {
1109                                                 rc = roc_nix_bpf_connect(nix,
1110                                                         lvl_flag,
1111                                                         base_mtr->bpf_id,
1112                                                         next_mtr->bpf_id);
1113                                                 if (rc)
1114                                                         return rc;
1115                                         }
1116                                 }
1117                                 cur_mtr_id = base_mtr->next_id;
1118                         }
1119                 }
1120         }
1121         return 0;
1122 }
1123
1124 int
1125 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1126 {
1127         struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1128         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1129         struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1130         uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1131         uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1132         uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1133         uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1134         int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1135         struct roc_nix *nix = &dev->nix;
1136         struct roc_nix_bpf_precolor tbl;
1137         struct roc_nix_bpf_cfg cfg;
1138         struct roc_nix_rq *rq;
1139         uint8_t lvl_mask;
1140         uint32_t i;
1141         uint32_t j;
1142         int rc;
1143
1144         mtr[0] = nix_mtr_find(dev, id);
1145         if (mtr[0] == NULL)
1146                 return -EINVAL;
1147
1148         num_mtr[0] = 1;
1149         idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1150         if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1151                 return -EINVAL;
1152
1153         lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1154         if (mtr[0]->is_used)
1155                 per_lvl_cnt[idx0] = 0;
1156         else
1157                 per_lvl_cnt[idx0] = 1;
1158
1159         if (mtr[0]->is_next) {
1160                 mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1161                 if (mtr[1] == NULL)
1162                         return -EINVAL;
1163                 num_mtr[1] = 1;
1164                 idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1165                 if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1166                         return -EINVAL;
1167
1168                 lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1169                 if (mtr[1]->is_used)
1170                         per_lvl_cnt[idx1] = 0;
1171                 else
1172                         per_lvl_cnt[idx1] = 1;
1173         }
1174
1175         if (mtr[1] && mtr[1]->is_next) {
1176                 mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1177                 if (mtr[2] == NULL)
1178                         return -EINVAL;
1179
1180                 num_mtr[2] = 1;
1181                 idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1182                 if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1183                         return -EINVAL;
1184
1185                 lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1186                 if (mtr[2]->is_used)
1187                         per_lvl_cnt[idx2] = 0;
1188                 else
1189                         per_lvl_cnt[idx2] = 1;
1190         }
1191
1192         rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1193         if (rc)
1194                 return rc;
1195         if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1196                 mtr[0]->bpf_id = profs[idx0].ids[0];
1197
1198         if (num_mtr[0])
1199                 if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1200                         if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1201                                 mtr[1]->bpf_id = profs[idx1].ids[0];
1202
1203         if (num_mtr[1])
1204                 if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1205                         if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1206                                 mtr[2]->bpf_id = profs[idx2].ids[0];
1207
1208         for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1209                 if (num_mtr[i]) {
1210                         if (!mtr[i]->is_used) {
1211                                 memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1212                                 nix_mtr_config_map(mtr[i], &cfg);
1213                                 rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1214                                                         lvl_map[mtr[i]->level],
1215                                                         &cfg);
1216
1217                                 memset(&tbl, 0,
1218                                        sizeof(struct roc_nix_bpf_precolor));
1219                                 nix_dscp_table_map(mtr[i], &tbl);
1220                                 rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1221                                         mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1222                                         &tbl);
1223
1224                                 if (mtr[i]->params.meter_enable) {
1225                                         for (j = 0; j < mtr[i]->rq_num; j++) {
1226                                                 rq = &dev->rqs[mtr[i]->rq_id
1227                                                                        [j]];
1228                                                 rc = roc_nix_bpf_ena_dis(nix,
1229                                                         mtr[i]->bpf_id, rq,
1230                                                         true);
1231                                         }
1232                                 }
1233                         }
1234                 }
1235         }
1236
1237         return rc;
1238 }
1239
1240 int
1241 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1242                               uint32_t *prev_id, uint32_t *next_id,
1243                               struct cnxk_mtr_policy_node *policy,
1244                               int *tree_level)
1245 {
1246         uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1247         uint32_t action_fate_green =
1248                 policy->actions[RTE_COLOR_GREEN].action_fate;
1249         uint32_t action_fate_yellow =
1250                 policy->actions[RTE_COLOR_YELLOW].action_fate;
1251         uint32_t cur_mtr_id = *next_id;
1252         uint32_t next_mtr_id = 0xffff;
1253         uint32_t prev_mtr_id = 0xffff;
1254         struct cnxk_meter_node *mtr;
1255
1256         if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1257                 next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1258
1259         if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1260                 next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1261
1262         if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1263                 next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1264
1265         if (next_mtr_id != 0xffff) {
1266                 switch (*tree_level) {
1267                 case 0:
1268                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1269                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1270                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1271                                 nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1272                                                      next_mtr_id);
1273                         } else {
1274                                 if (mtr->level == 0)
1275                                         mtr->is_used = true;
1276                                 else
1277                                         return -EINVAL;
1278                         }
1279                         (*tree_level)++;
1280                         *next_id = next_mtr_id;
1281                         break;
1282                 case 1:
1283                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1284                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1285                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1286                                 prev_mtr_id = id;
1287                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1288                                                      prev_mtr_id, next_mtr_id);
1289                         } else {
1290                                 if (mtr->level == 1) {
1291                                         mtr->prev_cnt++;
1292                                         prev_mtr_id = id;
1293                                         nix_mtr_chain_update(eth_dev,
1294                                                 cur_mtr_id, prev_mtr_id,
1295                                                 next_mtr_id);
1296
1297                                         mtr->is_used = true;
1298                                 } else {
1299                                         return -EINVAL;
1300                                 }
1301                         }
1302                         (*tree_level)++;
1303                         *next_id = next_mtr_id;
1304                         *prev_id = cur_mtr_id;
1305                         break;
1306                 case 2:
1307                         nix_mtr_chain_reset(eth_dev, id);
1308                         return -EINVAL;
1309                 }
1310         } else {
1311                 switch (*tree_level) {
1312                 case 0:
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, 0);
1316                         } else {
1317                                 if (mtr->level == 0)
1318                                         mtr->is_used = true;
1319                                 else
1320                                         return -EINVAL;
1321                         }
1322                         break;
1323                 case 1:
1324                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1325                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1326                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1327                                 prev_mtr_id = id;
1328                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1329                                                      prev_mtr_id, -1);
1330                         } else {
1331                                 if (mtr->level == 1) {
1332                                         mtr->prev_cnt++;
1333                                         prev_mtr_id = id;
1334                                         nix_mtr_chain_update(eth_dev,
1335                                                              cur_mtr_id,
1336                                                              prev_mtr_id, -1);
1337                                         mtr->is_used = true;
1338                                 } else {
1339                                         return -EINVAL;
1340                                 }
1341                         }
1342                         break;
1343                 case 2:
1344                         mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1345                         if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1346                                 nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1347                                 prev_mtr_id = *prev_id;
1348                                 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1349                                                      prev_mtr_id, -1);
1350                         } else {
1351                                 if (mtr->level == 2) {
1352                                         mtr->prev_cnt++;
1353                                         prev_mtr_id = *prev_id;
1354                                         nix_mtr_chain_update(eth_dev,
1355                                                              cur_mtr_id,
1356                                                              prev_mtr_id, -1);
1357                                         mtr->is_used = true;
1358                                 } else {
1359                                         return -EINVAL;
1360                                 }
1361                         }
1362                         break;
1363                 }
1364                 *next_id = 0xffff;
1365         }
1366
1367         return 0;
1368 }
1369
1370 int
1371 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev)
1372 {
1373         struct rte_mtr_capabilities capa;
1374         struct rte_mtr_error error;
1375
1376         return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1377 }