Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include <cnxk_ethdev.h>
5 : : #include <cnxk_tm.h>
6 : : #include <cnxk_utils.h>
7 : :
8 : : static int
9 [ # # ]: 0 : cnxk_nix_tm_node_type_get(struct rte_eth_dev *eth_dev, uint32_t node_id,
10 : : int *is_leaf, struct rte_tm_error *error)
11 : : {
12 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
13 : 0 : struct roc_nix *nix = &dev->nix;
14 : : struct roc_nix_tm_node *node;
15 : :
16 [ # # ]: 0 : if (is_leaf == NULL) {
17 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
18 : 0 : return -EINVAL;
19 : : }
20 : :
21 : 0 : node = roc_nix_tm_node_get(nix, node_id);
22 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL || !node) {
23 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
24 : 0 : return -EINVAL;
25 : : }
26 : :
27 [ # # ]: 0 : if (roc_nix_tm_lvl_is_leaf(nix, node->lvl))
28 : 0 : *is_leaf = true;
29 : : else
30 : 0 : *is_leaf = false;
31 : :
32 : : return 0;
33 : : }
34 : :
35 : : static int
36 : 0 : cnxk_nix_tm_capa_get(struct rte_eth_dev *eth_dev,
37 : : struct rte_tm_capabilities *cap,
38 : : struct rte_tm_error *error)
39 : : {
40 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
41 : : int rc, max_nr_nodes = 0, i, n_lvl;
42 : 0 : struct roc_nix *nix = &dev->nix;
43 : : uint16_t schq[ROC_TM_LVL_MAX];
44 : :
45 : : memset(cap, 0, sizeof(*cap));
46 : :
47 : 0 : rc = roc_nix_tm_rsrc_count(nix, schq);
48 [ # # ]: 0 : if (rc) {
49 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
50 : 0 : error->message = "unexpected fatal error";
51 : 0 : return rc;
52 : : }
53 : :
54 [ # # ]: 0 : for (i = 0; i < NIX_TXSCH_LVL_TL1; i++)
55 : 0 : max_nr_nodes += schq[i];
56 : :
57 : 0 : cap->n_nodes_max = max_nr_nodes + dev->nb_txq;
58 : :
59 : 0 : n_lvl = roc_nix_tm_lvl_cnt_get(nix);
60 : : /* Consider leaf level */
61 : 0 : cap->n_levels_max = n_lvl + 1;
62 : 0 : cap->non_leaf_nodes_identical = 1;
63 : 0 : cap->leaf_nodes_identical = 1;
64 : :
65 : : /* Shaper Capabilities */
66 : 0 : cap->shaper_private_n_max = max_nr_nodes;
67 : 0 : cap->shaper_n_max = max_nr_nodes;
68 : 0 : cap->shaper_private_dual_rate_n_max = max_nr_nodes;
69 : 0 : cap->shaper_private_rate_min = NIX_TM_MIN_SHAPER_RATE / 8;
70 : 0 : cap->shaper_private_rate_max = NIX_TM_MAX_SHAPER_RATE / 8;
71 : 0 : cap->shaper_private_packet_mode_supported = 1;
72 : 0 : cap->shaper_private_byte_mode_supported = 1;
73 : 0 : cap->shaper_pkt_length_adjust_min = NIX_TM_LENGTH_ADJUST_MIN;
74 : 0 : cap->shaper_pkt_length_adjust_max = NIX_TM_LENGTH_ADJUST_MAX;
75 : :
76 : : /* Schedule Capabilities */
77 : 0 : cap->sched_n_children_max = schq[n_lvl - 1];
78 : 0 : cap->sched_sp_n_priorities_max = NIX_TM_TLX_SP_PRIO_MAX;
79 : 0 : cap->sched_wfq_n_children_per_group_max = cap->sched_n_children_max;
80 [ # # ]: 0 : cap->sched_wfq_n_groups_max = 1;
81 : 0 : cap->sched_wfq_weight_max = roc_nix_tm_max_sched_wt_get();
82 : 0 : cap->sched_wfq_packet_mode_supported = 1;
83 : 0 : cap->sched_wfq_byte_mode_supported = 1;
84 : :
85 : 0 : cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_PARENT_KEEP_LEVEL |
86 : : RTE_TM_UPDATE_NODE_SUSPEND_RESUME;
87 : 0 : cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES |
88 : : RTE_TM_STATS_N_PKTS_RED_DROPPED |
89 : : RTE_TM_STATS_N_BYTES_RED_DROPPED;
90 : :
91 : 0 : cap->mark_vlan_dei_supported[RTE_COLOR_GREEN] = false;
92 : 0 : cap->mark_ip_ecn_tcp_supported[RTE_COLOR_GREEN] = false;
93 : 0 : cap->mark_ip_ecn_sctp_supported[RTE_COLOR_GREEN] = false;
94 : 0 : cap->mark_ip_dscp_supported[RTE_COLOR_GREEN] = false;
95 : :
96 [ # # ]: 0 : for (i = RTE_COLOR_YELLOW; i < RTE_COLORS; i++) {
97 : 0 : cap->mark_vlan_dei_supported[i] = true;
98 : 0 : cap->mark_ip_ecn_tcp_supported[i] = true;
99 : 0 : cap->mark_ip_ecn_sctp_supported[i] = true;
100 : 0 : cap->mark_ip_dscp_supported[i] = true;
101 : : }
102 : :
103 : : return 0;
104 : : }
105 : :
106 : : static int
107 : 0 : cnxk_nix_tm_level_capa_get(struct rte_eth_dev *eth_dev, uint32_t lvl,
108 : : struct rte_tm_level_capabilities *cap,
109 : : struct rte_tm_error *error)
110 : : {
111 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
112 : 0 : struct roc_nix *nix = &dev->nix;
113 : : uint16_t schq[ROC_TM_LVL_MAX];
114 : : int rc, n_lvl;
115 : :
116 : : memset(cap, 0, sizeof(*cap));
117 : :
118 : 0 : rc = roc_nix_tm_rsrc_count(nix, schq);
119 [ # # ]: 0 : if (rc) {
120 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
121 : 0 : error->message = "unexpected fatal error";
122 : 0 : return rc;
123 : : }
124 : :
125 : 0 : n_lvl = roc_nix_tm_lvl_cnt_get(nix);
126 : :
127 [ # # ]: 0 : if (roc_nix_tm_lvl_is_leaf(nix, lvl)) {
128 : : /* Leaf */
129 : 0 : cap->n_nodes_max = dev->nb_txq;
130 : 0 : cap->n_nodes_leaf_max = dev->nb_txq;
131 : 0 : cap->leaf_nodes_identical = 1;
132 : 0 : cap->leaf.stats_mask =
133 : : RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
134 : :
135 [ # # ]: 0 : } else if (lvl == ROC_TM_LVL_ROOT) {
136 : : /* Root node, a.k.a. TL2(vf)/TL1(pf) */
137 : 0 : cap->n_nodes_max = 1;
138 : 0 : cap->n_nodes_nonleaf_max = 1;
139 : 0 : cap->non_leaf_nodes_identical = 1;
140 : :
141 : 0 : cap->nonleaf.shaper_private_supported = true;
142 : 0 : cap->nonleaf.shaper_private_dual_rate_supported =
143 : 0 : roc_nix_tm_lvl_have_link_access(nix, lvl) ? false :
144 : : true;
145 : 0 : cap->nonleaf.shaper_private_rate_min =
146 : : NIX_TM_MIN_SHAPER_RATE / 8;
147 : 0 : cap->nonleaf.shaper_private_rate_max =
148 : : NIX_TM_MAX_SHAPER_RATE / 8;
149 : 0 : cap->nonleaf.shaper_private_packet_mode_supported = 1;
150 : 0 : cap->nonleaf.shaper_private_byte_mode_supported = 1;
151 : :
152 : 0 : cap->nonleaf.sched_n_children_max = schq[lvl];
153 : 0 : cap->nonleaf.sched_sp_n_priorities_max =
154 : 0 : roc_nix_tm_max_prio(nix, lvl) + 1;
155 [ # # ]: 0 : cap->nonleaf.sched_wfq_n_groups_max = 1;
156 : 0 : cap->nonleaf.sched_wfq_weight_max =
157 : : roc_nix_tm_max_sched_wt_get();
158 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 1;
159 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 1;
160 : :
161 [ # # ]: 0 : if (roc_nix_tm_lvl_have_link_access(nix, lvl))
162 : 0 : cap->nonleaf.stats_mask =
163 : : RTE_TM_STATS_N_PKTS_RED_DROPPED |
164 : : RTE_TM_STATS_N_BYTES_RED_DROPPED;
165 [ # # ]: 0 : } else if (lvl < ROC_TM_LVL_MAX) {
166 : : /* TL2, TL3, TL4, MDQ */
167 : 0 : cap->n_nodes_max = schq[lvl];
168 : 0 : cap->n_nodes_nonleaf_max = cap->n_nodes_max;
169 : 0 : cap->non_leaf_nodes_identical = 1;
170 : :
171 : 0 : cap->nonleaf.shaper_private_supported = true;
172 : 0 : cap->nonleaf.shaper_private_dual_rate_supported = true;
173 : 0 : cap->nonleaf.shaper_private_rate_min =
174 : : NIX_TM_MIN_SHAPER_RATE / 8;
175 : 0 : cap->nonleaf.shaper_private_rate_max =
176 : : NIX_TM_MAX_SHAPER_RATE / 8;
177 : 0 : cap->nonleaf.shaper_private_packet_mode_supported = 1;
178 : 0 : cap->nonleaf.shaper_private_byte_mode_supported = 1;
179 : :
180 : : /* MDQ doesn't support Strict Priority */
181 [ # # ]: 0 : if ((int)lvl == (n_lvl - 1))
182 : 0 : cap->nonleaf.sched_n_children_max = dev->nb_txq;
183 : : else
184 : 0 : cap->nonleaf.sched_n_children_max = schq[lvl - 1];
185 : 0 : cap->nonleaf.sched_sp_n_priorities_max =
186 : 0 : roc_nix_tm_max_prio(nix, lvl) + 1;
187 [ # # ]: 0 : cap->nonleaf.sched_wfq_n_groups_max = 1;
188 : 0 : cap->nonleaf.sched_wfq_weight_max =
189 : : roc_nix_tm_max_sched_wt_get();
190 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 1;
191 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 1;
192 : : } else {
193 : : /* unsupported level */
194 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
195 : 0 : return rc;
196 : : }
197 : : return 0;
198 : : }
199 : :
200 : : static int
201 : 0 : cnxk_nix_tm_node_capa_get(struct rte_eth_dev *eth_dev, uint32_t node_id,
202 : : struct rte_tm_node_capabilities *cap,
203 : : struct rte_tm_error *error)
204 : : {
205 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
206 : : struct cnxk_nix_tm_node *tm_node;
207 : 0 : struct roc_nix *nix = &dev->nix;
208 : : uint16_t schq[ROC_TM_LVL_MAX];
209 : : int rc, n_lvl, lvl;
210 : :
211 : : memset(cap, 0, sizeof(*cap));
212 : :
213 : 0 : tm_node = (struct cnxk_nix_tm_node *)roc_nix_tm_node_get(nix, node_id);
214 [ # # ]: 0 : if (!tm_node) {
215 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
216 : 0 : error->message = "no such node";
217 : 0 : return -EINVAL;
218 : : }
219 : :
220 : 0 : lvl = tm_node->nix_node.lvl;
221 : 0 : n_lvl = roc_nix_tm_lvl_cnt_get(nix);
222 : :
223 : : /* Leaf node */
224 [ # # ]: 0 : if (roc_nix_tm_lvl_is_leaf(nix, lvl)) {
225 : 0 : cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
226 : 0 : return 0;
227 : : }
228 : :
229 : 0 : rc = roc_nix_tm_rsrc_count(nix, schq);
230 [ # # ]: 0 : if (rc) {
231 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
232 : 0 : error->message = "unexpected fatal error";
233 : 0 : return rc;
234 : : }
235 : :
236 : : /* Non Leaf Shaper */
237 : 0 : cap->shaper_private_supported = true;
238 : 0 : cap->shaper_private_rate_min = NIX_TM_MIN_SHAPER_RATE / 8;
239 : 0 : cap->shaper_private_rate_max = NIX_TM_MAX_SHAPER_RATE / 8;
240 : 0 : cap->shaper_private_packet_mode_supported = 1;
241 : 0 : cap->shaper_private_byte_mode_supported = 1;
242 : :
243 : : /* Non Leaf Scheduler */
244 [ # # ]: 0 : if (lvl == (n_lvl - 1))
245 : 0 : cap->nonleaf.sched_n_children_max = dev->nb_txq;
246 : : else
247 : 0 : cap->nonleaf.sched_n_children_max = schq[lvl - 1];
248 : :
249 : 0 : cap->nonleaf.sched_sp_n_priorities_max =
250 : 0 : roc_nix_tm_max_prio(nix, lvl) + 1;
251 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max =
252 : 0 : cap->nonleaf.sched_n_children_max;
253 [ # # ]: 0 : cap->nonleaf.sched_wfq_n_groups_max = 1;
254 : 0 : cap->nonleaf.sched_wfq_weight_max = roc_nix_tm_max_sched_wt_get();
255 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 1;
256 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 1;
257 : :
258 : 0 : cap->shaper_private_dual_rate_supported = true;
259 [ # # ]: 0 : if (roc_nix_tm_lvl_have_link_access(nix, lvl)) {
260 : 0 : cap->shaper_private_dual_rate_supported = false;
261 : 0 : cap->stats_mask = RTE_TM_STATS_N_PKTS_RED_DROPPED |
262 : : RTE_TM_STATS_N_BYTES_RED_DROPPED;
263 : : }
264 : :
265 : : return 0;
266 : : }
267 : :
268 : : static int
269 : 0 : cnxk_nix_tm_shaper_profile_add(struct rte_eth_dev *eth_dev, uint32_t id,
270 : : const struct rte_tm_shaper_params *params,
271 : : struct rte_tm_error *error)
272 : : {
273 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
274 : : struct cnxk_nix_tm_shaper_profile *profile;
275 : 0 : struct roc_nix *nix = &dev->nix;
276 : : int rc;
277 : :
278 [ # # ]: 0 : if (roc_nix_tm_shaper_profile_get(nix, id)) {
279 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
280 : 0 : error->message = "shaper profile ID exist";
281 : 0 : return -EINVAL;
282 : : }
283 : :
284 : 0 : profile = rte_zmalloc("cnxk_nix_tm_shaper_profile",
285 : : sizeof(struct cnxk_nix_tm_shaper_profile), 0);
286 [ # # ]: 0 : if (!profile)
287 : : return -ENOMEM;
288 : 0 : profile->profile.id = id;
289 : 0 : profile->profile.commit_rate = params->committed.rate;
290 : 0 : profile->profile.peak_rate = params->peak.rate;
291 : 0 : profile->profile.commit_sz = params->committed.size;
292 : 0 : profile->profile.peak_sz = params->peak.size;
293 : : /* If Byte mode, then convert to bps */
294 [ # # ]: 0 : if (!params->packet_mode) {
295 : 0 : profile->profile.commit_rate *= 8;
296 : 0 : profile->profile.peak_rate *= 8;
297 : 0 : profile->profile.commit_sz *= 8;
298 : 0 : profile->profile.peak_sz *= 8;
299 : : }
300 : 0 : profile->profile.pkt_len_adj = params->pkt_length_adjust;
301 : 0 : profile->profile.pkt_mode = params->packet_mode;
302 : 0 : profile->profile.free_fn = rte_free;
303 [ # # ]: 0 : rte_memcpy(&profile->params, params,
304 : : sizeof(struct rte_tm_shaper_params));
305 : :
306 : 0 : rc = roc_nix_tm_shaper_profile_add(nix, &profile->profile);
307 : :
308 : : /* fill error information based on return value */
309 [ # # ]: 0 : if (rc) {
310 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
311 : 0 : error->message = roc_error_msg_get(rc);
312 : : }
313 : :
314 : : return rc;
315 : : }
316 : :
317 : : static int
318 : 0 : cnxk_nix_tm_shaper_profile_delete(struct rte_eth_dev *eth_dev,
319 : : uint32_t profile_id,
320 : : struct rte_tm_error *error)
321 : : {
322 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
323 : 0 : struct roc_nix *nix = &dev->nix;
324 : : int rc;
325 : :
326 : 0 : rc = roc_nix_tm_shaper_profile_delete(nix, profile_id);
327 [ # # ]: 0 : if (rc) {
328 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
329 : 0 : error->message = roc_error_msg_get(rc);
330 : : }
331 : :
332 : 0 : return rc;
333 : : }
334 : :
335 : : static int
336 : 0 : cnxk_nix_tm_node_add(struct rte_eth_dev *eth_dev, uint32_t node_id,
337 : : uint32_t parent_node_id, uint32_t priority,
338 : : uint32_t weight, uint32_t lvl,
339 : : const struct rte_tm_node_params *params,
340 : : struct rte_tm_error *error)
341 : : {
342 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
343 : : struct roc_nix_tm_shaper_profile *profile;
344 : : struct roc_nix_tm_node *parent_node;
345 : 0 : struct roc_nix *nix = &dev->nix;
346 : : struct cnxk_nix_tm_node *node;
347 : : int rc;
348 : :
349 : : /* we don't support dynamic updates */
350 [ # # ]: 0 : if (roc_nix_tm_is_user_hierarchy_enabled(nix)) {
351 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
352 : 0 : error->message = "dynamic update not supported";
353 : 0 : return -EIO;
354 : : }
355 : :
356 : 0 : parent_node = roc_nix_tm_node_get(nix, parent_node_id);
357 : : /* find the right level */
358 [ # # ]: 0 : if (lvl == RTE_TM_NODE_LEVEL_ID_ANY) {
359 [ # # ]: 0 : if (parent_node_id == RTE_TM_NODE_ID_NULL) {
360 : : lvl = ROC_TM_LVL_ROOT;
361 [ # # ]: 0 : } else if (parent_node) {
362 : 0 : lvl = parent_node->lvl + 1;
363 : : } else {
364 : : /* Neither proper parent nor proper level id given */
365 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
366 : 0 : error->message = "invalid parent node id";
367 : 0 : return -ERANGE;
368 : : }
369 : : }
370 : :
371 : 0 : node = rte_zmalloc("cnxk_nix_tm_node", sizeof(struct cnxk_nix_tm_node),
372 : : 0);
373 [ # # ]: 0 : if (!node)
374 : : return -ENOMEM;
375 : :
376 [ # # ]: 0 : rte_memcpy(&node->params, params, sizeof(struct rte_tm_node_params));
377 : :
378 : 0 : node->nix_node.id = node_id;
379 : 0 : node->nix_node.parent_id = parent_node_id;
380 : 0 : node->nix_node.priority = priority;
381 : 0 : node->nix_node.weight = weight;
382 : 0 : node->nix_node.lvl = lvl;
383 : 0 : node->nix_node.shaper_profile_id = params->shaper_profile_id;
384 : :
385 : 0 : profile = roc_nix_tm_shaper_profile_get(nix, params->shaper_profile_id);
386 : : /* Packet mode */
387 [ # # # # ]: 0 : if (!roc_nix_tm_lvl_is_leaf(nix, lvl) &&
388 [ # # ]: 0 : ((profile && profile->pkt_mode) ||
389 [ # # ]: 0 : (params->nonleaf.wfq_weight_mode &&
390 [ # # ]: 0 : params->nonleaf.n_sp_priorities &&
391 [ # # ]: 0 : !params->nonleaf.wfq_weight_mode[0])))
392 : 0 : node->nix_node.pkt_mode = 1;
393 : :
394 : 0 : rc = roc_nix_tm_node_add(nix, &node->nix_node);
395 [ # # ]: 0 : if (rc < 0) {
396 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
397 : 0 : error->message = roc_error_msg_get(rc);
398 : 0 : return rc;
399 : : }
400 : 0 : error->type = RTE_TM_ERROR_TYPE_NONE;
401 : 0 : roc_nix_tm_shaper_default_red_algo(&node->nix_node, profile);
402 : :
403 : 0 : return 0;
404 : : }
405 : :
406 : : static int
407 : 0 : cnxk_nix_tm_node_delete(struct rte_eth_dev *eth_dev, uint32_t node_id,
408 : : struct rte_tm_error *error)
409 : : {
410 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
411 : 0 : struct roc_nix *nix = &dev->nix;
412 : : struct cnxk_nix_tm_node *node;
413 : : int rc;
414 : :
415 : : /* we don't support dynamic updates yet */
416 [ # # ]: 0 : if (roc_nix_tm_is_user_hierarchy_enabled(nix)) {
417 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
418 : 0 : error->message = "hierarchy exists";
419 : 0 : return -EIO;
420 : : }
421 : :
422 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
423 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
424 : 0 : error->message = "invalid node id";
425 : 0 : return -EINVAL;
426 : : }
427 : :
428 : 0 : node = (struct cnxk_nix_tm_node *)roc_nix_tm_node_get(nix, node_id);
429 : :
430 : 0 : rc = roc_nix_tm_node_delete(nix, node_id, 0);
431 [ # # ]: 0 : if (rc) {
432 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
433 : 0 : error->message = roc_error_msg_get(rc);
434 : : } else {
435 : 0 : rte_free(node);
436 : : }
437 : :
438 : : return rc;
439 : : }
440 : :
441 : : static int
442 : 0 : cnxk_nix_tm_node_suspend(struct rte_eth_dev *eth_dev, uint32_t node_id,
443 : : struct rte_tm_error *error)
444 : : {
445 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
446 : : int rc;
447 : :
448 : 0 : rc = roc_nix_tm_node_suspend_resume(&dev->nix, node_id, true);
449 [ # # ]: 0 : if (rc) {
450 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
451 : 0 : error->message = roc_error_msg_get(rc);
452 : : }
453 : :
454 : 0 : return rc;
455 : : }
456 : :
457 : : static int
458 : 0 : cnxk_nix_tm_node_resume(struct rte_eth_dev *eth_dev, uint32_t node_id,
459 : : struct rte_tm_error *error)
460 : : {
461 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
462 : : int rc;
463 : :
464 : 0 : rc = roc_nix_tm_node_suspend_resume(&dev->nix, node_id, false);
465 [ # # ]: 0 : if (rc) {
466 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
467 : 0 : error->message = roc_error_msg_get(rc);
468 : : }
469 : :
470 : 0 : return rc;
471 : : }
472 : :
473 : : static int
474 : 0 : cnxk_nix_tm_hierarchy_commit(struct rte_eth_dev *eth_dev,
475 : : int clear_on_fail __rte_unused,
476 : : struct rte_tm_error *error)
477 : : {
478 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
479 : 0 : struct roc_nix *nix = &dev->nix;
480 : : int rc;
481 : :
482 [ # # ]: 0 : if (roc_nix_tm_is_user_hierarchy_enabled(nix)) {
483 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
484 : 0 : error->message = "hierarchy exists";
485 : 0 : return -EIO;
486 : : }
487 : :
488 [ # # ]: 0 : if (roc_nix_tm_leaf_cnt(nix) < dev->nb_txq) {
489 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
490 : 0 : error->message = "incomplete hierarchy";
491 : 0 : return -EINVAL;
492 : : }
493 : :
494 : 0 : rc = roc_nix_tm_hierarchy_disable(nix);
495 [ # # ]: 0 : if (rc) {
496 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
497 : 0 : error->message = roc_error_msg_get(rc);
498 : 0 : return -EIO;
499 : : }
500 : :
501 : 0 : rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_USER, true);
502 [ # # ]: 0 : if (rc) {
503 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
504 : 0 : error->message = roc_error_msg_get(rc);
505 : 0 : return -EIO;
506 : : }
507 : 0 : error->type = RTE_TM_ERROR_TYPE_NONE;
508 : :
509 : 0 : return 0;
510 : : }
511 : :
512 : : static int
513 : 0 : cnxk_nix_tm_node_shaper_update(struct rte_eth_dev *eth_dev, uint32_t node_id,
514 : : uint32_t profile_id, struct rte_tm_error *error)
515 : : {
516 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
517 : : struct roc_nix_tm_shaper_profile *profile;
518 : 0 : struct roc_nix *nix = &dev->nix;
519 : : struct roc_nix_tm_node *node;
520 : : int rc;
521 : :
522 : 0 : rc = roc_nix_tm_node_shaper_update(nix, node_id, profile_id, false);
523 [ # # ]: 0 : if (rc) {
524 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
525 : 0 : error->message = roc_error_msg_get(rc);
526 : 0 : return -EINVAL;
527 : : }
528 : 0 : node = roc_nix_tm_node_get(nix, node_id);
529 [ # # ]: 0 : if (!node)
530 : : return -EINVAL;
531 : :
532 : 0 : profile = roc_nix_tm_shaper_profile_get(nix, profile_id);
533 : 0 : roc_nix_tm_shaper_default_red_algo(node, profile);
534 : :
535 : 0 : return 0;
536 : : }
537 : :
538 : : static int
539 : 0 : cnxk_nix_tm_node_parent_update(struct rte_eth_dev *eth_dev, uint32_t node_id,
540 : : uint32_t new_parent_id, uint32_t priority,
541 : : uint32_t weight, struct rte_tm_error *error)
542 : : {
543 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
544 : 0 : struct roc_nix *nix = &dev->nix;
545 : : int rc;
546 : :
547 : 0 : rc = roc_nix_tm_node_parent_update(nix, node_id, new_parent_id,
548 : : priority, weight);
549 [ # # ]: 0 : if (rc) {
550 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
551 : 0 : error->message = roc_error_msg_get(rc);
552 : 0 : return -EINVAL;
553 : : }
554 : :
555 : : return 0;
556 : : }
557 : :
558 : : static int
559 : 0 : cnxk_nix_tm_node_stats_read(struct rte_eth_dev *eth_dev, uint32_t node_id,
560 : : struct rte_tm_node_stats *stats,
561 : : uint64_t *stats_mask, int clear,
562 : : struct rte_tm_error *error)
563 : : {
564 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
565 : : struct roc_nix_tm_node_stats nix_tm_stats;
566 : 0 : struct roc_nix *nix = &dev->nix;
567 : : struct roc_nix_tm_node *node;
568 : : int rc;
569 : :
570 : 0 : node = roc_nix_tm_node_get(nix, node_id);
571 [ # # ]: 0 : if (!node) {
572 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
573 : 0 : error->message = "no such node";
574 : 0 : return -EINVAL;
575 : : }
576 : :
577 [ # # ]: 0 : if (roc_nix_tm_lvl_is_leaf(nix, node->lvl)) {
578 : : struct roc_nix_stats_queue qstats;
579 : :
580 : 0 : rc = roc_nix_stats_queue_get(nix, node->id, 0, &qstats);
581 [ # # ]: 0 : if (!rc) {
582 : 0 : stats->n_pkts = qstats.tx_pkts;
583 : 0 : stats->n_bytes = qstats.tx_octs;
584 : 0 : *stats_mask =
585 : : RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
586 : : }
587 : 0 : goto exit;
588 : : }
589 : :
590 : 0 : rc = roc_nix_tm_node_stats_get(nix, node_id, clear, &nix_tm_stats);
591 [ # # ]: 0 : if (!rc) {
592 : 0 : stats->leaf.n_pkts_dropped[RTE_COLOR_RED] =
593 : 0 : nix_tm_stats.stats[ROC_NIX_TM_NODE_PKTS_DROPPED];
594 : 0 : stats->leaf.n_bytes_dropped[RTE_COLOR_RED] =
595 : 0 : nix_tm_stats.stats[ROC_NIX_TM_NODE_BYTES_DROPPED];
596 : 0 : *stats_mask = RTE_TM_STATS_N_PKTS_RED_DROPPED |
597 : : RTE_TM_STATS_N_BYTES_RED_DROPPED;
598 : : }
599 : :
600 : 0 : exit:
601 [ # # ]: 0 : if (rc) {
602 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
603 : 0 : error->message = roc_error_msg_get(rc);
604 : : }
605 : : return rc;
606 : : }
607 : :
608 : : int
609 [ # # ]: 0 : cnxk_nix_tm_mark_vlan_dei(struct rte_eth_dev *eth_dev, int mark_green,
610 : : int mark_yellow, int mark_red,
611 : : struct rte_tm_error *error)
612 : : {
613 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
614 : 0 : struct roc_nix *roc_nix = &dev->nix;
615 : : int rc;
616 : :
617 [ # # ]: 0 : if (mark_green) {
618 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
619 : 0 : error->message = "Green VLAN marking not supported";
620 : 0 : return -EINVAL;
621 : : }
622 : :
623 [ # # ]: 0 : if (eth_dev->data->dev_started) {
624 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
625 : 0 : error->message = "VLAN DEI mark for running ports not "
626 : : "supported";
627 : 0 : return -EBUSY;
628 : : }
629 : :
630 : 0 : rc = roc_nix_tm_mark_config(roc_nix, ROC_NIX_TM_MARK_VLAN_DEI,
631 : : mark_yellow, mark_red);
632 [ # # ]: 0 : if (rc) {
633 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
634 : 0 : error->message = roc_error_msg_get(rc);
635 : : }
636 : : return rc;
637 : : }
638 : :
639 : : int
640 [ # # ]: 0 : cnxk_nix_tm_mark_ip_ecn(struct rte_eth_dev *eth_dev, int mark_green,
641 : : int mark_yellow, int mark_red,
642 : : struct rte_tm_error *error)
643 : : {
644 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
645 : 0 : struct roc_nix *roc_nix = &dev->nix;
646 : : int rc;
647 : :
648 [ # # ]: 0 : if (mark_green) {
649 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
650 : 0 : error->message = "Green IP ECN marking not supported";
651 : 0 : return -EINVAL;
652 : : }
653 : :
654 [ # # ]: 0 : if (eth_dev->data->dev_started) {
655 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
656 : 0 : error->message = "IP ECN mark for running ports not "
657 : : "supported";
658 : 0 : return -EBUSY;
659 : : }
660 : :
661 : 0 : rc = roc_nix_tm_mark_config(roc_nix, ROC_NIX_TM_MARK_IPV4_ECN,
662 : : mark_yellow, mark_red);
663 [ # # ]: 0 : if (rc < 0)
664 : 0 : goto exit;
665 : :
666 : 0 : rc = roc_nix_tm_mark_config(roc_nix, ROC_NIX_TM_MARK_IPV6_ECN,
667 : : mark_yellow, mark_red);
668 : 0 : exit:
669 [ # # ]: 0 : if (rc < 0) {
670 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
671 : 0 : error->message = roc_error_msg_get(rc);
672 : : }
673 : : return rc;
674 : : }
675 : :
676 : : int
677 [ # # ]: 0 : cnxk_nix_tm_mark_ip_dscp(struct rte_eth_dev *eth_dev, int mark_green,
678 : : int mark_yellow, int mark_red,
679 : : struct rte_tm_error *error)
680 : : {
681 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
682 : 0 : struct roc_nix *roc_nix = &dev->nix;
683 : : int rc;
684 : :
685 [ # # ]: 0 : if (mark_green) {
686 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
687 : 0 : error->message = "Green IP DSCP marking not supported";
688 : 0 : return -EINVAL;
689 : : }
690 : :
691 [ # # ]: 0 : if (eth_dev->data->dev_started) {
692 : 0 : error->type = RTE_TM_ERROR_TYPE_CAPABILITIES;
693 : 0 : error->message = "IP DSCP mark for running ports not "
694 : : "supported";
695 : 0 : return -EBUSY;
696 : : }
697 : :
698 : 0 : rc = roc_nix_tm_mark_config(roc_nix, ROC_NIX_TM_MARK_IPV4_DSCP,
699 : : mark_yellow, mark_red);
700 [ # # ]: 0 : if (rc < 0)
701 : 0 : goto exit;
702 : :
703 : 0 : rc = roc_nix_tm_mark_config(roc_nix, ROC_NIX_TM_MARK_IPV6_DSCP,
704 : : mark_yellow, mark_red);
705 : 0 : exit:
706 [ # # ]: 0 : if (rc < 0) {
707 : 0 : error->type = roc_nix_tm_err_to_rte_err(rc);
708 : 0 : error->message = roc_error_msg_get(rc);
709 : : }
710 : : return rc;
711 : : }
712 : :
713 : : struct rte_tm_ops cnxk_tm_ops = {
714 : : .node_type_get = cnxk_nix_tm_node_type_get,
715 : : .capabilities_get = cnxk_nix_tm_capa_get,
716 : : .level_capabilities_get = cnxk_nix_tm_level_capa_get,
717 : : .node_capabilities_get = cnxk_nix_tm_node_capa_get,
718 : :
719 : : .shaper_profile_add = cnxk_nix_tm_shaper_profile_add,
720 : : .shaper_profile_delete = cnxk_nix_tm_shaper_profile_delete,
721 : :
722 : : .node_add = cnxk_nix_tm_node_add,
723 : : .node_delete = cnxk_nix_tm_node_delete,
724 : : .node_suspend = cnxk_nix_tm_node_suspend,
725 : : .node_resume = cnxk_nix_tm_node_resume,
726 : : .hierarchy_commit = cnxk_nix_tm_hierarchy_commit,
727 : :
728 : : .node_shaper_update = cnxk_nix_tm_node_shaper_update,
729 : : .node_parent_update = cnxk_nix_tm_node_parent_update,
730 : : .node_stats_read = cnxk_nix_tm_node_stats_read,
731 : :
732 : : .mark_vlan_dei = cnxk_nix_tm_mark_vlan_dei,
733 : : .mark_ip_ecn = cnxk_nix_tm_mark_ip_ecn,
734 : : .mark_ip_dscp = cnxk_nix_tm_mark_ip_dscp,
735 : : };
736 : :
737 : : int
738 : 0 : cnxk_nix_tm_ops_get(struct rte_eth_dev *eth_dev __rte_unused, void *arg)
739 : : {
740 [ # # ]: 0 : if (!arg)
741 : : return -EINVAL;
742 : :
743 : : /* Check for supported revisions */
744 [ # # # # ]: 0 : if (roc_model_is_cn96_ax() || roc_model_is_cn95_a0())
745 : : return -EINVAL;
746 : :
747 : 0 : *(const void **)arg = &cnxk_tm_ops;
748 : :
749 : 0 : return 0;
750 : : }
751 : :
752 : : int
753 [ # # ]: 0 : cnxk_nix_tm_set_queue_rate_limit(struct rte_eth_dev *eth_dev,
754 : : uint16_t queue_idx, uint32_t tx_rate_mbps)
755 : : {
756 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
757 : 0 : uint64_t tx_rate = tx_rate_mbps * (uint64_t)1E6;
758 [ # # ]: 0 : struct roc_nix *nix = &dev->nix;
759 : : int rc = -EINVAL;
760 : :
761 : : /* Check for supported revisions */
762 [ # # # # ]: 0 : if (roc_model_is_cn96_ax() || roc_model_is_cn95_a0())
763 : 0 : goto exit;
764 : :
765 [ # # ]: 0 : if (queue_idx >= eth_dev->data->nb_tx_queues)
766 : 0 : goto exit;
767 : :
768 [ # # ]: 0 : if (roc_nix_tm_tree_type_get(nix) == ROC_NIX_TM_PFC)
769 : 0 : return roc_nix_tm_pfc_rlimit_sq(nix, queue_idx, tx_rate);
770 : :
771 [ # # ]: 0 : if ((roc_nix_tm_tree_type_get(nix) != ROC_NIX_TM_RLIMIT) &&
772 [ # # ]: 0 : eth_dev->data->nb_tx_queues > 1) {
773 : : /*
774 : : * Disable xmit will be enabled when
775 : : * new topology is available.
776 : : */
777 : 0 : rc = roc_nix_tm_hierarchy_disable(nix);
778 [ # # ]: 0 : if (rc)
779 : 0 : goto exit;
780 : :
781 : 0 : rc = roc_nix_tm_prepare_rate_limited_tree(nix);
782 [ # # ]: 0 : if (rc)
783 : 0 : goto exit;
784 : :
785 : 0 : rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_RLIMIT, true);
786 [ # # ]: 0 : if (rc)
787 : 0 : goto exit;
788 : : }
789 : :
790 : 0 : return roc_nix_tm_rlimit_sq(nix, queue_idx, tx_rate);
791 : : exit:
792 : : return rc;
793 : : }
|