Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
3 : : */
4 : :
5 : : #include <rte_ethdev.h>
6 : : #include <rte_tm_driver.h>
7 : :
8 : : #include "sxe2_tm.h"
9 : : #include "sxe2_ethdev.h"
10 : : #include "sxe2_common_log.h"
11 : : #include "sxe2_cmd_chnl.h"
12 : :
13 : 0 : static uint16_t sxe2_tm_level_node_num_get(uint8_t level)
14 : : {
15 : 0 : uint16_t node_num = 0;
16 : :
17 : 0 : switch (level) {
18 : : case 0:
19 : : node_num = SXE2_TM_1L_NODE_NUM_MAX;
20 : : break;
21 : : case 1:
22 : : node_num = SXE2_TM_2L_NODE_NUM_MAX;
23 : : break;
24 : : case 2:
25 : : node_num = SXE2_TM_3L_NODE_NUM_MAX;
26 : : break;
27 : : case 3:
28 : : node_num = SXE2_TM_4L_NODE_NUM_MAX;
29 : : break;
30 : : }
31 : 0 : return node_num;
32 : : }
33 : :
34 : 0 : static int32_t sxe2_tm_capabilities_get(struct rte_eth_dev *dev,
35 : : struct rte_tm_capabilities *cap,
36 : : struct rte_tm_error *error)
37 : : {
38 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
39 : 0 : int32_t ret = 0;
40 : 0 : uint32_t i;
41 : :
42 [ # # ]: 0 : if (!cap || !error) {
43 : 0 : PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
44 : 0 : ret = -EINVAL;
45 : 0 : goto l_end;
46 : : }
47 : :
48 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
49 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
50 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
51 : 0 : error->message = "The TM capability is not supported.";
52 : 0 : ret = ENOTSUP;
53 : 0 : goto l_end;
54 : : }
55 : :
56 : 0 : error->type = RTE_TM_ERROR_TYPE_NONE;
57 : 0 : memset(cap, 0, sizeof(struct rte_tm_capabilities));
58 : :
59 [ # # ]: 0 : for (i = 0; i < adapter->tm_ctxt.tm_layers; i++)
60 [ # # ]: 0 : cap->n_nodes_max += sxe2_tm_level_node_num_get(i);
61 : :
62 : 0 : cap->n_levels_max = adapter->tm_ctxt.tm_layers;
63 : :
64 : 0 : cap->non_leaf_nodes_identical = 1;
65 : :
66 : 0 : cap->leaf_nodes_identical = 1;
67 : :
68 : 0 : cap->shaper_n_max = cap->n_nodes_max;
69 : :
70 : 0 : cap->shaper_private_n_max = cap->n_nodes_max;
71 : :
72 : 0 : cap->shaper_private_dual_rate_n_max = cap->n_nodes_max;
73 : :
74 : 0 : cap->shaper_private_rate_min = 0;
75 : :
76 : 0 : cap->shaper_private_rate_max = 12500000000ull;
77 : :
78 : 0 : cap->shaper_private_packet_mode_supported = 0;
79 : 0 : cap->shaper_private_byte_mode_supported = 1;
80 : :
81 : 0 : cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
82 : :
83 : 0 : cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
84 : :
85 : 0 : cap->shaper_shared_n_max = 0;
86 : 0 : cap->shaper_shared_n_nodes_per_shaper_max = 0;
87 : 0 : cap->shaper_shared_n_shapers_per_node_max = 0;
88 : 0 : cap->shaper_shared_dual_rate_n_max = 0;
89 : 0 : cap->shaper_shared_rate_min = 0;
90 : 0 : cap->shaper_shared_rate_max = 0;
91 : 0 : cap->shaper_shared_packet_mode_supported = 0;
92 : 0 : cap->shaper_shared_byte_mode_supported = 0;
93 : :
94 : 0 : cap->sched_n_children_max = dev->data->nb_tx_queues;
95 : :
96 : 0 : cap->sched_sp_n_priorities_max = 7;
97 : :
98 : 0 : cap->sched_wfq_n_children_per_group_max = 1;
99 : 0 : cap->sched_wfq_n_groups_max = 0;
100 : 0 : cap->sched_wfq_weight_max = 0;
101 : 0 : cap->sched_wfq_packet_mode_supported = 0;
102 : 0 : cap->sched_wfq_byte_mode_supported = 0;
103 : :
104 : 0 : cap->cman_wred_packet_mode_supported = 0;
105 : 0 : cap->cman_wred_byte_mode_supported = 0;
106 : 0 : cap->cman_head_drop_supported = 0;
107 : 0 : cap->cman_wred_context_n_max = 0;
108 : 0 : cap->cman_wred_context_private_n_max = 0;
109 : 0 : cap->cman_wred_context_shared_n_max = 0;
110 : 0 : cap->cman_wred_context_shared_n_nodes_per_context_max = 0;
111 : 0 : cap->cman_wred_context_shared_n_contexts_per_node_max = 0;
112 : :
113 : 0 : cap->dynamic_update_mask = 0;
114 : :
115 : 0 : cap->stats_mask = 0;
116 : 0 : l_end:
117 : 0 : return ret;
118 : : }
119 : :
120 : 0 : static int32_t sxe2_level_capabilities_get(struct rte_eth_dev *dev,
121 : : uint32_t level_id, struct rte_tm_level_capabilities *cap,
122 : : struct rte_tm_error *error)
123 : : {
124 : 0 : int32_t ret = 0;
125 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
126 : :
127 [ # # ]: 0 : if (!cap || !error) {
128 : 0 : PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
129 : 0 : ret = -EINVAL;
130 : 0 : goto l_end;
131 : : }
132 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
133 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
134 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
135 : 0 : error->message = "The TM capability is not supported.";
136 : 0 : ret = ENOTSUP;
137 : 0 : goto l_end;
138 : : }
139 : :
140 [ # # ]: 0 : if (level_id >= adapter->tm_ctxt.tm_layers) {
141 : 0 : ret = -EINVAL;
142 : 0 : error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
143 : 0 : error->message = "too deep level";
144 : 0 : goto l_end;
145 : : }
146 : :
147 [ # # ]: 0 : cap->n_nodes_max = sxe2_tm_level_node_num_get(level_id);
148 : :
149 : 0 : cap->non_leaf_nodes_identical = true;
150 : :
151 : 0 : cap->leaf_nodes_identical = true;
152 : :
153 [ # # ]: 0 : if (level_id != adapter->tm_ctxt.tm_layers - 1) {
154 : 0 : cap->n_nodes_nonleaf_max = cap->n_nodes_max;
155 : 0 : cap->n_nodes_leaf_max = 0;
156 : :
157 : 0 : cap->nonleaf.shaper_private_supported = true;
158 : 0 : cap->nonleaf.shaper_private_dual_rate_supported = true;
159 : 0 : cap->nonleaf.shaper_private_rate_min = 0;
160 : :
161 : 0 : cap->nonleaf.shaper_private_rate_max = 12500000000ull;
162 : 0 : cap->nonleaf.shaper_private_packet_mode_supported = 0;
163 : 0 : cap->nonleaf.shaper_private_byte_mode_supported = 1;
164 : :
165 : 0 : cap->nonleaf.shaper_shared_n_max = 0;
166 : 0 : cap->nonleaf.shaper_shared_packet_mode_supported = 0;
167 : 0 : cap->nonleaf.shaper_shared_byte_mode_supported = 0;
168 : :
169 : 0 : cap->nonleaf.sched_n_children_max = SXE2_TM_MAX_CHILDREN_COUNT;
170 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 7;
171 : :
172 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
173 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
174 : 0 : cap->nonleaf.sched_wfq_weight_max = 0;
175 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 0;
176 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 0;
177 : :
178 : 0 : cap->nonleaf.stats_mask = 0;
179 : : } else {
180 : 0 : cap->n_nodes_nonleaf_max = 0;
181 : 0 : cap->n_nodes_leaf_max = cap->n_nodes_max;
182 : :
183 : 0 : cap->leaf.shaper_private_supported = true;
184 : 0 : cap->leaf.shaper_private_dual_rate_supported = true;
185 : 0 : cap->leaf.shaper_private_rate_min = 0;
186 : 0 : cap->leaf.shaper_private_rate_max = 12500000000ull;
187 : 0 : cap->leaf.shaper_private_packet_mode_supported = 0;
188 : 0 : cap->leaf.shaper_private_byte_mode_supported = 1;
189 : :
190 : 0 : cap->leaf.shaper_shared_n_max = 0;
191 : 0 : cap->leaf.shaper_shared_packet_mode_supported = 0;
192 : 0 : cap->leaf.shaper_shared_byte_mode_supported = 0;
193 : :
194 : 0 : cap->leaf.cman_head_drop_supported = false;
195 : 0 : cap->leaf.cman_wred_context_private_supported = false;
196 : 0 : cap->leaf.cman_wred_context_shared_n_max = 0;
197 : :
198 : 0 : cap->leaf.stats_mask = 0;
199 : : }
200 : :
201 : 0 : l_end:
202 : 0 : return ret;
203 : : }
204 : :
205 : 0 : static struct sxe2_tm_node *sxe2_tm_find_node(struct sxe2_tm_node *parent, uint32_t id)
206 : : {
207 : 0 : struct sxe2_tm_node *node = NULL;
208 : 0 : uint32_t i;
209 : :
210 [ # # # # ]: 0 : if (parent == NULL || parent->id == id) {
211 : 0 : node = parent;
212 : 0 : goto l_end;
213 : : }
214 : :
215 [ # # ]: 0 : for (i = 0; i < parent->child_cnt; i++) {
216 : 0 : node = sxe2_tm_find_node(parent->children[i], id);
217 [ # # ]: 0 : if (node)
218 : 0 : goto l_end;
219 : : }
220 : :
221 : 0 : l_end:
222 : 0 : return node;
223 : : }
224 : :
225 : 0 : static int32_t sxe2_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
226 : : struct rte_tm_node_capabilities *cap,
227 : : struct rte_tm_error *error)
228 : : {
229 : 0 : int32_t ret = -EINVAL;
230 : 0 : struct sxe2_tm_node *tm_node;
231 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
232 : :
233 [ # # ]: 0 : if (!cap || !error) {
234 : 0 : PMD_LOG_ERR(DRV, "sxe2 get tm cap failed, cap or error is NULL.");
235 : 0 : ret = -EINVAL;
236 : 0 : goto l_end;
237 : : }
238 : :
239 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
240 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
241 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
242 : 0 : error->message = "The TM capability is not supported.";
243 : 0 : ret = ENOTSUP;
244 : 0 : goto l_end;
245 : : }
246 : :
247 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
248 : 0 : PMD_LOG_ERR(DRV, "invalid node id");
249 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
250 : 0 : error->message = "invalid node id";
251 : 0 : goto l_end;
252 : : }
253 : :
254 : 0 : tm_node = sxe2_tm_find_node(adapter->tm_ctxt.root, node_id);
255 [ # # ]: 0 : if (!tm_node) {
256 : 0 : PMD_LOG_ERR(DRV, "no such node");
257 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
258 : 0 : error->message = "no such node";
259 : 0 : goto l_end;
260 : : }
261 : :
262 : 0 : cap->shaper_private_supported = true;
263 : 0 : cap->shaper_private_dual_rate_supported = true;
264 : 0 : cap->shaper_private_rate_min = 0;
265 : 0 : cap->shaper_private_rate_max = 12500000000ull;
266 : 0 : cap->shaper_private_packet_mode_supported = 0;
267 : 0 : cap->shaper_private_byte_mode_supported = 1;
268 : :
269 : 0 : cap->shaper_shared_n_max = 0;
270 : 0 : cap->shaper_shared_packet_mode_supported = 0;
271 : 0 : cap->shaper_shared_byte_mode_supported = 0;
272 : :
273 [ # # ]: 0 : if (tm_node->level == adapter->tm_ctxt.tm_layers - 1) {
274 : 0 : cap->leaf.cman_head_drop_supported = false;
275 : 0 : cap->leaf.cman_wred_context_private_supported = false;
276 : 0 : cap->leaf.cman_wred_context_shared_n_max = 0;
277 : : } else {
278 : 0 : cap->nonleaf.sched_n_children_max = SXE2_TM_MAX_CHILDREN_COUNT;
279 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 7;
280 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
281 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
282 : 0 : cap->nonleaf.sched_wfq_weight_max = 0;
283 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 0;
284 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 0;
285 : : }
286 : 0 : cap->stats_mask = 0;
287 : :
288 : 0 : ret = 0;
289 : 0 : l_end:
290 : 0 : return ret;
291 : : }
292 : :
293 : 0 : static int32_t sxe2_tm_shaper_profile_param_check(const struct rte_tm_shaper_params *profile,
294 : : struct rte_tm_error *error)
295 : : {
296 : 0 : int32_t ret = 0;
297 : :
298 [ # # ]: 0 : if (profile->committed.size) {
299 : 0 : PMD_LOG_ERR(DRV, "committed bucket size not supported.");
300 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
301 : 0 : error->message = "committed bucket size not supported";
302 : 0 : ret = -EINVAL;
303 : 0 : goto l_end;
304 : : }
305 : :
306 [ # # ]: 0 : if (profile->peak.size) {
307 : 0 : PMD_LOG_ERR(DRV, "peak bucket size not supported.");
308 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
309 : 0 : error->message = "peak bucket size not supported";
310 : 0 : ret = -EINVAL;
311 : 0 : goto l_end;
312 : : }
313 : :
314 [ # # ]: 0 : if (profile->pkt_length_adjust) {
315 : 0 : PMD_LOG_ERR(DRV, "packet length adjustment not supported.");
316 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
317 : 0 : error->message = "packet length adjustment not supported";
318 : 0 : ret = -EINVAL;
319 : 0 : goto l_end;
320 : : }
321 : :
322 [ # # ]: 0 : if (profile->committed.rate > SXE2_HW_RATE_MAX ||
323 : : profile->committed.rate < SXE2_HW_RATE_MIN) {
324 : 0 : PMD_LOG_ERR(DRV, "The committed rate limit value is required to be in "
325 : : "the range [%" PRIu64 ", %" PRIu64 "].",
326 : : (uint64_t)SXE2_HW_RATE_MIN, (uint64_t)SXE2_HW_RATE_MAX);
327 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
328 : 0 : error->message = "invalid rate limit: value out of range.";
329 : 0 : ret = -EINVAL;
330 : 0 : goto l_end;
331 : : }
332 : :
333 [ # # ]: 0 : if (profile->peak.rate > SXE2_HW_RATE_MAX ||
334 : : profile->peak.rate < SXE2_HW_RATE_MIN) {
335 : 0 : PMD_LOG_ERR(DRV, "The peak rate limit value is required to be in "
336 : : "the range [%" PRIu64 ", %" PRIu64 "].",
337 : : (uint64_t)SXE2_HW_RATE_MIN, (uint64_t)SXE2_HW_RATE_MAX);
338 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE;
339 : 0 : error->message = "invalid rate limit: value out of range.";
340 : 0 : ret = -EINVAL;
341 : 0 : goto l_end;
342 : : }
343 : :
344 [ # # ]: 0 : if (profile->committed.rate > profile->peak.rate) {
345 : 0 : PMD_LOG_ERR(DRV, "committed rate can't be greater than peak rate.");
346 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
347 : 0 : error->message = "committed rate can't be greater than peak rate.";
348 : 0 : ret = -EINVAL;
349 : 0 : goto l_end;
350 : : }
351 : 0 : l_end:
352 : 0 : return ret;
353 : : }
354 : :
355 : : static inline struct sxe2_tm_shaper_profile *
356 : 0 : sxe2_tm_shaper_profile_search(struct rte_eth_dev *dev, uint32_t id)
357 : : {
358 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
359 : 0 : struct sxe2_shaper_profile_list *shaper_profile_list =
360 : : &adapter->tm_ctxt.profile_list;
361 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
362 : :
363 [ # # # # : 0 : TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
# # ]
364 [ # # # # : 0 : if (id == shaper_profile->id)
# # ]
365 : 0 : goto l_end;
366 : : }
367 : :
368 : : shaper_profile = NULL;
369 : :
370 : 0 : l_end:
371 : 0 : return shaper_profile;
372 : : }
373 : :
374 : 0 : static int32_t sxe2_tm_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
375 : : const struct rte_tm_shaper_params *profile,
376 : : struct rte_tm_error *error)
377 : : {
378 : 0 : int32_t ret = -EINVAL;
379 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
380 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
381 : :
382 [ # # ]: 0 : if (!profile || !error) {
383 : 0 : PMD_LOG_ERR(DRV, "Invalid input: profile:0x%p or error:0x%p is null.",
384 : : profile, error);
385 [ # # ]: 0 : if (error) {
386 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
387 : 0 : error->message = "Invalid input: profile or error is null.";
388 : : }
389 : 0 : ret = -EINVAL;
390 : 0 : goto l_end;
391 : : }
392 : :
393 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
394 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
395 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
396 : 0 : error->message = "The TM capability is not supported.";
397 : 0 : ret = ENOTSUP;
398 : 0 : goto l_end;
399 : : }
400 : :
401 : 0 : ret = sxe2_tm_shaper_profile_param_check(profile, error);
402 [ # # ]: 0 : if (ret)
403 : 0 : goto l_end;
404 : :
405 : 0 : shaper_profile = sxe2_tm_shaper_profile_search(dev, shaper_profile_id);
406 [ # # ]: 0 : if (shaper_profile) {
407 : 0 : PMD_LOG_ERR(DRV, "profile ID exist.");
408 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
409 : 0 : error->message = "profile ID exist";
410 : 0 : ret = -EINVAL;
411 : 0 : goto l_end;
412 : : }
413 : :
414 : 0 : shaper_profile = rte_zmalloc("sxe2_tm_shaper_profile",
415 : : sizeof(struct sxe2_tm_shaper_profile), 0);
416 [ # # ]: 0 : if (!shaper_profile) {
417 : 0 : PMD_LOG_ERR(DRV, "Alloc shaper_profile memory failed.");
418 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
419 : 0 : error->message = "Alloc shaper_profile memory failed";
420 : 0 : ret = -ENOMEM;
421 : 0 : goto l_end;
422 : : }
423 : :
424 : 0 : rte_memcpy(&shaper_profile->profile, profile,
425 : : sizeof(struct rte_tm_shaper_params));
426 : 0 : shaper_profile->id = shaper_profile_id;
427 : :
428 : 0 : TAILQ_INSERT_TAIL(&adapter->tm_ctxt.profile_list, shaper_profile, node);
429 : 0 : l_end:
430 : 0 : return ret;
431 : : }
432 : :
433 : 0 : static int32_t sxe2_tm_shaper_profile_del(struct rte_eth_dev *dev,
434 : : uint32_t id, struct rte_tm_error *error)
435 : : {
436 : 0 : int32_t ret = -EINVAL;
437 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
438 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
439 : :
440 [ # # ]: 0 : if (!error) {
441 : 0 : PMD_LOG_ERR(DRV, "Error param is null.");
442 : 0 : goto l_end;
443 : : }
444 : :
445 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
446 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
447 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
448 : 0 : error->message = "The TM capability is not supported.";
449 : 0 : ret = ENOTSUP;
450 : 0 : goto l_end;
451 : : }
452 : :
453 : 0 : shaper_profile = sxe2_tm_shaper_profile_search(dev, id);
454 [ # # ]: 0 : if (!shaper_profile) {
455 : 0 : PMD_LOG_ERR(DRV, "profile ID not exist.");
456 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
457 : 0 : error->message = "profile ID not exist";
458 : 0 : ret = -EINVAL;
459 : 0 : goto l_end;
460 : : }
461 : :
462 [ # # ]: 0 : if (shaper_profile->ref_cnt) {
463 : 0 : PMD_LOG_ERR(DRV, "profile in use.");
464 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
465 : 0 : error->message = "profile in use";
466 : 0 : ret = -EINVAL;
467 : 0 : goto l_end;
468 : : }
469 : :
470 [ # # ]: 0 : TAILQ_REMOVE(&adapter->tm_ctxt.profile_list, shaper_profile, node);
471 : 0 : rte_free(shaper_profile);
472 : :
473 : 0 : ret = 0;
474 : 0 : l_end:
475 : 0 : return ret;
476 : : }
477 : :
478 : 0 : static int32_t sxe2_tm_node_param_check(struct rte_eth_dev *dev,
479 : : uint32_t parent_node_type,
480 : : uint32_t node_id, uint32_t priority, uint32_t weight,
481 : : const struct rte_tm_node_params *params,
482 : : bool is_leaf, struct rte_tm_error *error)
483 : : {
484 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
485 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
486 : 0 : int32_t ret = -EINVAL;
487 : :
488 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
489 : 0 : PMD_LOG_ERR(DRV, "Invalid node id.");
490 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
491 : 0 : error->message = "invalid node id";
492 : 0 : goto l_end;
493 : : }
494 : :
495 [ # # ]: 0 : if (parent_node_type == SXE2_TM_NODE_TYPE_VSIG &&
496 [ # # ]: 0 : priority >= tm_ctxt->prio_max) {
497 : 0 : PMD_LOG_ERR(DRV, "Priority should be less than %u.", tm_ctxt->prio_max);
498 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
499 : 0 : error->message = "The priority is too high.";
500 : 0 : goto l_end;
501 : : }
502 : :
503 [ # # ]: 0 : if (priority > SXE2_TM_PRIO_MAX) {
504 : 0 : PMD_LOG_ERR(DRV, "Priority should be less than %u.", SXE2_TM_PRIO_MAX);
505 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
506 : 0 : error->message = "The priority is too high.";
507 : 0 : goto l_end;
508 : : }
509 : :
510 [ # # ]: 0 : if (weight > SXE2_TM_WEIGHT_MAX || weight < SXE2_TM_WEIGHT_MIN) {
511 : 0 : PMD_LOG_ERR(DRV, "Weight must be between 1 and 200.");
512 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
513 : 0 : error->message = "weight must be between 1 and 200";
514 : 0 : goto l_end;
515 : : }
516 : :
517 [ # # ]: 0 : if (params->shared_shaper_id) {
518 : 0 : PMD_LOG_ERR(DRV, "Shared shaper not supported.");
519 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
520 : 0 : error->message = "shared shaper not supported";
521 : 0 : goto l_end;
522 : : }
523 [ # # ]: 0 : if (params->n_shared_shapers) {
524 : 0 : PMD_LOG_ERR(DRV, "Shared shaper not supported..");
525 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
526 : 0 : error->message = "shared shaper not supported";
527 : 0 : goto l_end;
528 : : }
529 : :
530 [ # # ]: 0 : if (!is_leaf) {
531 [ # # ]: 0 : if (node_id <= dev->data->nb_tx_queues) {
532 : 0 : PMD_LOG_ERR(DRV, "no leaf node id must bigger than queue id.");
533 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
534 : 0 : error->message = "no leaf node id must bigger than queue id.";
535 : 0 : goto l_end;
536 : : }
537 : :
538 [ # # ]: 0 : if (params->nonleaf.wfq_weight_mode) {
539 : 0 : PMD_LOG_ERR(DRV, "WFQ not supported.");
540 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
541 : 0 : error->message = "WFQ not supported";
542 : 0 : goto l_end;
543 : : }
544 : :
545 [ # # ]: 0 : if (params->nonleaf.n_sp_priorities != 1) {
546 : 0 : PMD_LOG_ERR(DRV, "SP priority not supported.");
547 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
548 : 0 : error->message = "SP priority not supported";
549 : 0 : goto l_end;
550 : : }
551 : : } else {
552 [ # # ]: 0 : if (node_id >= dev->data->nb_tx_queues) {
553 : 0 : PMD_LOG_ERR(DRV, "leaf node id must be queue id.");
554 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
555 : 0 : error->message = "leaf node id must be queue id.";
556 : 0 : goto l_end;
557 : : }
558 : :
559 [ # # ]: 0 : if (params->leaf.cman) {
560 : 0 : PMD_LOG_ERR(DRV, "Congestion management not supported.");
561 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
562 : 0 : error->message = "Congestion management not supported";
563 : 0 : goto l_end;
564 : : }
565 [ # # ]: 0 : if (params->leaf.wred.wred_profile_id != RTE_TM_WRED_PROFILE_ID_NONE) {
566 : 0 : PMD_LOG_ERR(DRV, "WRED not supported.");
567 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
568 : 0 : error->message = "WRED not supported";
569 : 0 : goto l_end;
570 : : }
571 [ # # ]: 0 : if (params->leaf.wred.shared_wred_context_id) {
572 : 0 : PMD_LOG_ERR(DRV, "WRED not supported.");
573 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
574 : 0 : error->message = "WRED not supported";
575 : 0 : goto l_end;
576 : : }
577 [ # # ]: 0 : if (params->leaf.wred.n_shared_wred_contexts) {
578 : 0 : PMD_LOG_ERR(DRV, "WRED not supported.");
579 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
580 : 0 : error->message = "WRED not supported";
581 : 0 : goto l_end;
582 : : }
583 : : }
584 : : ret = 0;
585 : 0 : l_end:
586 : 0 : return ret;
587 : : }
588 : :
589 : 0 : static int32_t sxe2_tm_add_child(struct sxe2_tm_node *parent,
590 : : struct sxe2_tm_node *child)
591 : : {
592 : 0 : int32_t ret = -1;
593 : 0 : uint32_t i;
594 [ # # ]: 0 : for (i = 0; i < SXE2_TM_MAX_CHILDREN_COUNT; i++) {
595 [ # # ]: 0 : if (parent->children[i] == NULL) {
596 : 0 : parent->children[i] = child;
597 : 0 : child->index_in_parent = i;
598 : 0 : parent->child_cnt++;
599 : 0 : ret = 0;
600 : 0 : break;
601 : : }
602 : : }
603 : 0 : return ret;
604 : : }
605 : :
606 : 0 : static int32_t sxe2_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id, uint32_t parent_node_id,
607 : : uint32_t priority, uint32_t weight, uint32_t level_id,
608 : : const struct rte_tm_node_params *params,
609 : : struct rte_tm_error *error)
610 : : {
611 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
612 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
613 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
614 : 0 : struct sxe2_tm_node *tm_node = NULL;
615 : 0 : struct sxe2_tm_node *parent_node = NULL;
616 : 0 : int32_t ret = -EINVAL;
617 : 0 : bool is_leaf;
618 : :
619 [ # # ]: 0 : if (!params || !error) {
620 : 0 : PMD_LOG_ERR(DRV, "Invalid input: params:0x%p or error:0x%p is null.",
621 : : params, error);
622 [ # # ]: 0 : if (error) {
623 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
624 : 0 : error->message = "Invalid input: params or error is null.";
625 : : }
626 : 0 : ret = -EINVAL;
627 : 0 : goto l_end;
628 : : }
629 : :
630 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
631 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
632 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
633 : 0 : error->message = "The TM capability is not supported.";
634 : 0 : ret = ENOTSUP;
635 : 0 : goto l_end;
636 : : }
637 : :
638 : 0 : shaper_profile = sxe2_tm_shaper_profile_search(dev, params->shaper_profile_id);
639 [ # # ]: 0 : if (!shaper_profile) {
640 : 0 : PMD_LOG_ERR(DRV, "Shaper profile does not exist.");
641 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
642 : 0 : error->message = "shaper profile does not exist";
643 : 0 : ret = -EINVAL;
644 : 0 : goto l_end;
645 : : }
646 : :
647 [ # # ]: 0 : if (parent_node_id == RTE_TM_NODE_ID_NULL) {
648 [ # # ]: 0 : if (level_id != 0) {
649 : 0 : PMD_LOG_ERR(DRV, "Wrong level, root node (NULL parent) must be at level 0.");
650 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
651 : 0 : error->message = "Wrong level, root node (NULL parent) must be at level 0";
652 : 0 : ret = -EINVAL;
653 : 0 : goto l_end;
654 : : }
655 : :
656 [ # # ]: 0 : if (tm_ctxt->root) {
657 : 0 : PMD_LOG_ERR(DRV, "Already have a root.");
658 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
659 : 0 : error->message = "already have a root";
660 : 0 : ret = -EINVAL;
661 : 0 : goto l_end;
662 : : }
663 : :
664 : 0 : ret = sxe2_tm_node_param_check(dev, SXE2_TM_NODE_TYPE_INVALID, node_id, priority,
665 : : weight, params, false, error);
666 [ # # ]: 0 : if (ret)
667 : 0 : goto l_end;
668 : :
669 : 0 : tm_node = rte_zmalloc("tm_node_root", sizeof(struct sxe2_tm_node), 0);
670 [ # # ]: 0 : if (!tm_node) {
671 : 0 : PMD_LOG_ERR(DRV, "Alloc tm_node memory failed.");
672 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
673 : 0 : error->message = "Alloc tm_node memory failed";
674 : 0 : ret = -ENOMEM;
675 : 0 : goto l_end;
676 : : }
677 : :
678 : 0 : tm_node->id = node_id;
679 : 0 : tm_node->level = 0;
680 : 0 : tm_node->parent = NULL;
681 : 0 : tm_node->child_cnt = 0;
682 : 0 : tm_node->weight = weight;
683 : 0 : tm_node->hw_weight = SXE2_TM_WEIGHT_SUM;
684 : 0 : tm_node->type = SXE2_TM_NODE_TYPE_VSIG;
685 : 0 : tm_node->priority = priority;
686 : 0 : tm_node->shaper_profile = shaper_profile;
687 : :
688 : 0 : tm_node->teid = tm_ctxt->root_teid;
689 : :
690 : 0 : shaper_profile->ref_cnt++;
691 : 0 : tm_ctxt->root = tm_node;
692 : 0 : ret = 0;
693 : 0 : goto l_end;
694 : : }
695 : :
696 : 0 : parent_node = sxe2_tm_find_node(tm_ctxt->root, parent_node_id);
697 [ # # ]: 0 : if (!parent_node) {
698 : 0 : PMD_LOG_ERR(DRV, "Parent not exist.");
699 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
700 : 0 : error->message = "parent not exist";
701 : 0 : ret = -EINVAL;
702 : 0 : goto l_end;
703 : : }
704 : :
705 [ # # ]: 0 : if (parent_node->child_cnt >= SXE2_TM_MAX_CHILDREN_COUNT ||
706 [ # # ]: 0 : (parent_node->type == SXE2_TM_NODE_TYPE_VSIG &&
707 [ # # ]: 0 : parent_node->child_cnt >= tm_ctxt->root_max_children)) {
708 : 0 : PMD_LOG_ERR(DRV, "Parent node is full.");
709 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
710 : 0 : error->message = "parent node is full";
711 : 0 : ret = -EINVAL;
712 : 0 : goto l_end;
713 : : }
714 : :
715 [ # # ]: 0 : if (level_id == RTE_TM_NODE_LEVEL_ID_ANY) {
716 : 0 : level_id = parent_node->level + 1;
717 [ # # ]: 0 : } else if (level_id != parent_node->level + 1) {
718 : 0 : PMD_LOG_ERR(DRV, "Wrong level.");
719 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
720 : 0 : error->message = "Wrong level";
721 : 0 : ret = -EINVAL;
722 : 0 : goto l_end;
723 : : }
724 : :
725 [ # # ]: 0 : if (level_id >= tm_ctxt->tm_layers) {
726 : 0 : PMD_LOG_ERR(DRV, "The maximum number of TM configuration levels is %d",
727 : : tm_ctxt->tm_layers);
728 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
729 : 0 : error->message = "TM level exceeds supported hardware limit";
730 : 0 : ret = -EINVAL;
731 : 0 : goto l_end;
732 : : }
733 : :
734 [ # # ]: 0 : if (level_id + 1 == tm_ctxt->tm_layers)
735 : : is_leaf = true;
736 : : else
737 : 0 : is_leaf = false;
738 : :
739 : 0 : ret = sxe2_tm_node_param_check(dev, parent_node->type, node_id, priority, weight,
740 : : params, is_leaf, error);
741 [ # # ]: 0 : if (ret)
742 : 0 : goto l_end;
743 : :
744 [ # # ]: 0 : if (sxe2_tm_find_node(tm_ctxt->root, node_id)) {
745 : 0 : PMD_LOG_ERR(DRV, "Node id already used.");
746 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
747 : 0 : error->message = "node id already used";
748 : 0 : ret = -EINVAL;
749 : 0 : goto l_end;
750 : : }
751 : :
752 : 0 : tm_node = rte_zmalloc("tm_node_no_root", sizeof(struct sxe2_tm_node), 0);
753 [ # # ]: 0 : if (!tm_node) {
754 : 0 : PMD_LOG_ERR(DRV, "Alloc tm_node memory failed.");
755 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
756 : 0 : error->message = "Alloc tm_node memory failed";
757 : 0 : ret = -ENOMEM;
758 : 0 : goto l_end;
759 : : }
760 : :
761 [ # # ]: 0 : if (level_id + 1 != tm_ctxt->tm_layers)
762 : 0 : tm_node->type = SXE2_TM_NODE_TYPE_MID;
763 : : else
764 : 0 : tm_node->type = SXE2_TM_NODE_TYPE_QUEUE;
765 : 0 : tm_node->id = node_id;
766 : 0 : tm_node->level = level_id;
767 : 0 : tm_node->parent = parent_node;
768 : 0 : tm_node->child_cnt = 0;
769 : 0 : tm_node->weight = weight;
770 : 0 : tm_node->priority = priority;
771 : 0 : tm_node->shaper_profile = shaper_profile;
772 : 0 : shaper_profile->ref_cnt++;
773 : :
774 : 0 : ret = sxe2_tm_add_child(parent_node, tm_node);
775 : 0 : if (ret) {
776 : 0 : shaper_profile->ref_cnt--;
777 : 0 : rte_free(tm_node);
778 : : }
779 : 0 : l_end:
780 : 0 : return ret;
781 : : }
782 : :
783 : 0 : static int32_t sxe2_tm_tree_delete(struct sxe2_tm_node *tm_node)
784 : : {
785 : 0 : int32_t ret = 0;
786 : 0 : uint32_t i, j;
787 : 0 : struct sxe2_tm_node *parent = NULL;
788 : :
789 [ # # ]: 0 : if (!tm_node)
790 : 0 : goto l_end;
791 : :
792 : 0 : parent = tm_node->parent;
793 : :
794 [ # # ]: 0 : if (tm_node->child_cnt != 0) {
795 [ # # ]: 0 : for (i = SXE2_TM_MAX_CHILDREN_COUNT; i > 0; i--) {
796 [ # # ]: 0 : if (tm_node->children[i - 1])
797 : 0 : ret = sxe2_tm_tree_delete(tm_node->children[i - 1]);
798 : : }
799 : : }
800 : :
801 [ # # ]: 0 : if (tm_node->shaper_profile)
802 : 0 : tm_node->shaper_profile->ref_cnt--;
803 : :
804 [ # # # # ]: 0 : if (tm_node->type != SXE2_TM_NODE_TYPE_VSIG && parent) {
805 [ # # ]: 0 : for (i = 0; i < parent->child_cnt; i++) {
806 [ # # ]: 0 : if (parent->children[i] == tm_node)
807 : : break;
808 : : }
809 [ # # ]: 0 : for (j = i; j < parent->child_cnt - 1; j++)
810 : 0 : parent->children[j] = parent->children[j + 1];
811 : :
812 : 0 : parent->children[parent->child_cnt - 1] = NULL;
813 : 0 : parent->child_cnt--;
814 : : }
815 : 0 : rte_free(tm_node);
816 : 0 : tm_node = NULL;
817 : 0 : l_end:
818 : 0 : return ret;
819 : : }
820 : :
821 : 0 : static int32_t sxe2_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
822 : : struct rte_tm_error *error)
823 : : {
824 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
825 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
826 : 0 : struct sxe2_tm_node *tm_node = NULL;
827 : 0 : int32_t ret = -EINVAL;
828 : :
829 [ # # ]: 0 : if (!error) {
830 : 0 : PMD_LOG_ERR(DRV, "Invalid input: error is null.");
831 : 0 : ret = -EINVAL;
832 : 0 : goto l_end;
833 : : }
834 : :
835 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
836 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
837 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
838 : 0 : error->message = "The TM capability is not supported.";
839 : 0 : ret = ENOTSUP;
840 : 0 : goto l_end;
841 : : }
842 : :
843 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
844 : 0 : PMD_LOG_ERR(DRV, "Invalid node id. node_id = %u", node_id);
845 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
846 : 0 : error->message = "invalid node id";
847 : 0 : goto l_end;
848 : : }
849 : :
850 : 0 : tm_node = sxe2_tm_find_node(tm_ctxt->root, node_id);
851 [ # # ]: 0 : if (!tm_node) {
852 : 0 : PMD_LOG_ERR(DRV, "No such node.");
853 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
854 : 0 : error->message = "no such node";
855 : 0 : ret = -EINVAL;
856 : 0 : goto l_end;
857 : : }
858 : :
859 : 0 : ret = sxe2_tm_tree_delete(tm_node);
860 [ # # ]: 0 : if (ret) {
861 : 0 : PMD_LOG_ERR(DRV, "Delete node failed.");
862 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
863 : 0 : error->message = "Delete node failed";
864 : 0 : goto l_end;
865 : : }
866 : :
867 [ # # ]: 0 : if (tm_node == tm_ctxt->root)
868 : 0 : tm_ctxt->root = NULL;
869 : :
870 : 0 : l_end:
871 : 0 : return ret;
872 : : }
873 : :
874 : 0 : static int32_t sxe2_tm_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
875 : : int32_t *is_leaf, struct rte_tm_error *error)
876 : : {
877 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
878 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
879 : 0 : struct sxe2_tm_node *tm_node = NULL;
880 : 0 : int32_t ret = -EINVAL;
881 : :
882 [ # # ]: 0 : if (!is_leaf || !error) {
883 : 0 : PMD_LOG_ERR(DRV, "Invalid input: is_leaf:0x%p or error:0x%p is null.",
884 : : is_leaf, error);
885 [ # # ]: 0 : if (error) {
886 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
887 : 0 : error->message = "Invalid input: is_leaf or error is null";
888 : : }
889 : 0 : goto l_end;
890 : : }
891 : :
892 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
893 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
894 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
895 : 0 : error->message = "The TM capability is not supported.";
896 : 0 : ret = ENOTSUP;
897 : 0 : goto l_end;
898 : : }
899 : :
900 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
901 : 0 : PMD_LOG_ERR(DRV, "Invalid node id.");
902 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
903 : 0 : error->message = "invalid node id";
904 : 0 : goto l_end;
905 : : }
906 : :
907 : 0 : tm_node = sxe2_tm_find_node(tm_ctxt->root, node_id);
908 [ # # ]: 0 : if (!tm_node) {
909 : 0 : PMD_LOG_ERR(DRV, "No such node.");
910 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
911 : 0 : error->message = "no such node";
912 : 0 : goto l_end;
913 : : }
914 : :
915 [ # # ]: 0 : if (tm_node->level + 1 == tm_ctxt->tm_layers)
916 : 0 : *is_leaf = true;
917 : : else
918 : 0 : *is_leaf = false;
919 : : ret = 0;
920 : 0 : l_end:
921 : 0 : return ret;
922 : : }
923 : :
924 : 0 : int32_t sxe2_tm_uninit(struct rte_eth_dev *dev)
925 : : {
926 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
927 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
928 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
929 : 0 : int32_t ret = 0;
930 : :
931 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
932 : 0 : ret = 0;
933 : 0 : goto l_end;
934 : : }
935 : :
936 : 0 : tm_ctxt->tm_layers = 0;
937 : 0 : tm_ctxt->root_max_children = 0;
938 : 0 : tm_ctxt->committed = false;
939 : :
940 : 0 : (void)sxe2_tm_tree_delete(tm_ctxt->root);
941 : :
942 [ # # ]: 0 : while ((shaper_profile = TAILQ_FIRST(&tm_ctxt->profile_list))) {
943 [ # # ]: 0 : TAILQ_REMOVE(&tm_ctxt->profile_list, shaper_profile, node);
944 : 0 : rte_free(shaper_profile);
945 : : }
946 : 0 : l_end:
947 : 0 : return ret;
948 : : }
949 : :
950 : 0 : int32_t sxe2_tm_init(struct rte_eth_dev *dev)
951 : : {
952 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
953 : 0 : struct sxe2_sched_hw_cap *sched_ctxt = &adapter->sched_ctxt;
954 : 0 : struct sxe2_tm_context *tm_ctxt = &adapter->tm_ctxt;
955 : 0 : int32_t ret = 0;
956 : 0 : struct sxe2_tm_shaper_profile *shaper_profile = NULL;
957 : :
958 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0)
959 : 0 : goto l_end;
960 : :
961 : 0 : tm_ctxt->tm_layers = sched_ctxt->tm_layers;
962 : 0 : tm_ctxt->root_max_children = sched_ctxt->root_max_children;
963 : 0 : tm_ctxt->prio_max = sched_ctxt->prio_max;
964 : 0 : tm_ctxt->committed = false;
965 : 0 : TAILQ_INIT(&tm_ctxt->profile_list);
966 : 0 : tm_ctxt->root = NULL;
967 : :
968 : 0 : shaper_profile = rte_zmalloc("sxe2_tm_shaper_profile",
969 : : sizeof(struct sxe2_tm_shaper_profile), 0);
970 [ # # ]: 0 : if (!shaper_profile) {
971 : 0 : PMD_LOG_ERR(DRV, "Alloc shaper_profile memory failed.");
972 : 0 : ret = -ENOMEM;
973 : 0 : goto l_end;
974 : : }
975 : 0 : shaper_profile->id = RTE_TM_SHAPER_PROFILE_ID_NONE;
976 : 0 : shaper_profile->ref_cnt = 1;
977 : 0 : shaper_profile->profile.committed.rate = UINT64_MAX;
978 : 0 : shaper_profile->profile.peak.rate = UINT64_MAX;
979 : 0 : TAILQ_INSERT_TAIL(&tm_ctxt->profile_list, shaper_profile, node);
980 : :
981 : 0 : l_end:
982 : 0 : return ret;
983 : : }
984 : :
985 : 0 : static int32_t sxe2_tm_chk_all_leaf(struct rte_eth_dev *dev)
986 : : {
987 : 0 : int32_t ret = 0;
988 : 0 : uint32_t i = 0;
989 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
990 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
991 [ # # ]: 0 : if (!sxe2_tm_find_node(adapter->tm_ctxt.root, i)) {
992 : : ret = -1;
993 : : break;
994 : : }
995 : : }
996 : 0 : return ret;
997 : : }
998 : :
999 : 0 : static int32_t sxe2_tm_weight_calc(struct sxe2_tm_node *tm_node)
1000 : : {
1001 : 0 : int32_t ret = 0;
1002 : 0 : int32_t total_weight = 0;
1003 : 0 : int32_t total_weight2 = 0;
1004 : 0 : uint32_t i = 0;
1005 : 0 : uint32_t j = 0;
1006 : 0 : uint32_t k = 0;
1007 : 0 : uint32_t maxindex = 0;
1008 : 0 : uint32_t maxweight = 0;
1009 : 0 : struct sxe2_tm_node *cacl_node[SXE2_TM_MAX_CHILDREN_COUNT] = {NULL};
1010 : :
1011 [ # # ]: 0 : if (!tm_node) {
1012 : 0 : PMD_LOG_ERR(DRV, "Invalid input: tm_node is null.");
1013 : 0 : ret = -EINVAL;
1014 : 0 : goto l_end;
1015 : : }
1016 : :
1017 [ # # ]: 0 : if (tm_node->child_cnt == 0)
1018 : 0 : goto l_end;
1019 : :
1020 [ # # ]: 0 : for (j = SXE2_TM_PRIO_MIN; j <= SXE2_TM_PRIO_MAX; j++) {
1021 : : k = 0;
1022 : 0 : total_weight = 0;
1023 : 0 : total_weight2 = 0;
1024 : 0 : maxindex = 0;
1025 : 0 : maxweight = 0;
1026 : :
1027 [ # # ]: 0 : for (i = 0; i < tm_node->child_cnt; i++) {
1028 [ # # ]: 0 : if (tm_node->children[i]->priority == j)
1029 : 0 : cacl_node[k++] = tm_node->children[i];
1030 : : }
1031 [ # # ]: 0 : if (k == 0)
1032 : 0 : continue;
1033 : :
1034 [ # # ]: 0 : for (i = 0; i < k; i++)
1035 : 0 : total_weight += cacl_node[i]->weight;
1036 : :
1037 [ # # ]: 0 : for (i = 0; i < k; i++) {
1038 : 0 : cacl_node[i]->hw_weight = cacl_node[i]->weight *
1039 : 0 : SXE2_TM_WEIGHT_SUM / total_weight;
1040 : 0 : total_weight2 += cacl_node[i]->hw_weight;
1041 [ # # ]: 0 : if (cacl_node[i]->hw_weight > maxweight) {
1042 : 0 : maxweight = cacl_node[i]->hw_weight;
1043 : 0 : maxindex = i;
1044 : : }
1045 : : }
1046 : :
1047 : 0 : cacl_node[maxindex]->hw_weight += SXE2_TM_WEIGHT_SUM - total_weight2;
1048 : : }
1049 : :
1050 [ # # ]: 0 : for (i = 0; i < tm_node->child_cnt; i++) {
1051 : 0 : ret = sxe2_tm_weight_calc(tm_node->children[i]);
1052 [ # # ]: 0 : if (ret)
1053 : 0 : goto l_end;
1054 : : }
1055 : :
1056 : 0 : l_end:
1057 : 0 : return ret;
1058 : : }
1059 : :
1060 : 0 : static int32_t sxe2_tm_hierarchy_commit(struct rte_eth_dev *dev,
1061 : : int32_t clear_on_fail, struct rte_tm_error *error)
1062 : : {
1063 : 0 : struct sxe2_adapter *adapter = SXE2_DEV_PRIVATE_TO_ADAPTER(dev);
1064 : 0 : int32_t ret = -EINVAL;
1065 : :
1066 [ # # ]: 0 : if (!error) {
1067 : 0 : PMD_LOG_ERR(DRV, "Invalid input: error is null.");
1068 : 0 : ret = -EINVAL;
1069 : 0 : goto l_clear_on_fail;
1070 : : }
1071 : :
1072 [ # # ]: 0 : if ((adapter->cap_flags & SXE2_DEV_CAPS_OFFLOAD_TM) == 0) {
1073 : 0 : PMD_LOG_ERR(DRV, "The TM capability is not supported.");
1074 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1075 : 0 : error->message = "The TM capability is not supported.";
1076 : 0 : ret = ENOTSUP;
1077 : 0 : goto l_clear_on_fail;
1078 : : }
1079 : :
1080 [ # # ]: 0 : if (dev->data->dev_started) {
1081 : 0 : PMD_LOG_ERR(DRV, "Device failed to Stop.");
1082 : 0 : error->message = "Device failed to Stop";
1083 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1084 : 0 : ret = -EPERM;
1085 : 0 : goto l_clear_on_fail;
1086 : : }
1087 : :
1088 : 0 : ret = sxe2_tm_chk_all_leaf(dev);
1089 [ # # ]: 0 : if (ret) {
1090 : 0 : PMD_LOG_ERR(DRV, "All tx queues need config.");
1091 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1092 : 0 : error->message = "All tx queues need config.";
1093 : 0 : goto l_clear_on_fail;
1094 : : }
1095 : :
1096 : 0 : ret = sxe2_tm_weight_calc(adapter->tm_ctxt.root);
1097 [ # # ]: 0 : if (ret) {
1098 : 0 : PMD_LOG_ERR(DRV, "The weight in tree is wrong.");
1099 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1100 : 0 : error->message = "The weight in tree is wrong.";
1101 : 0 : goto l_clear_on_fail;
1102 : : }
1103 : :
1104 : 0 : ret = sxe2_drv_tm_commit(adapter);
1105 [ # # ]: 0 : if (ret) {
1106 : 0 : PMD_LOG_ERR(DRV, "Commit tree to fw failed.");
1107 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1108 : 0 : error->message = "Commit tree to fw failed.";
1109 : 0 : goto l_clear_on_fail;
1110 : : }
1111 : :
1112 : 0 : adapter->tm_ctxt.committed = true;
1113 : 0 : ret = 0;
1114 : 0 : goto l_end;
1115 : :
1116 : 0 : l_clear_on_fail:
1117 [ # # ]: 0 : if (clear_on_fail) {
1118 : 0 : (void)sxe2_tm_uninit(dev);
1119 : 0 : (void)sxe2_tm_init(dev);
1120 : : }
1121 : :
1122 : 0 : l_end:
1123 : 0 : return ret;
1124 : : }
1125 : :
1126 : : static const struct rte_tm_ops sxe2_tm_ops = {
1127 : : .capabilities_get = sxe2_tm_capabilities_get,
1128 : : .level_capabilities_get = sxe2_level_capabilities_get,
1129 : : .node_capabilities_get = sxe2_node_capabilities_get,
1130 : : .shaper_profile_add = sxe2_tm_shaper_profile_add,
1131 : : .shaper_profile_delete = sxe2_tm_shaper_profile_del,
1132 : : .node_add = sxe2_tm_node_add,
1133 : : .node_delete = sxe2_tm_node_delete,
1134 : : .node_type_get = sxe2_tm_node_type_get,
1135 : :
1136 : : .hierarchy_commit = sxe2_tm_hierarchy_commit,
1137 : : };
1138 : :
1139 : 0 : int32_t sxe2_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
1140 : : {
1141 : 0 : int32_t ret = 0;
1142 : :
1143 [ # # ]: 0 : if (!arg) {
1144 : 0 : ret = -EINVAL;
1145 : 0 : PMD_LOG_ERR(DRV, "%s failed because arg is NULL", __func__);
1146 : 0 : goto l_end;
1147 : : }
1148 : 0 : *(const void **)arg = &sxe2_tm_ops;
1149 : 0 : l_end:
1150 : 0 : return ret;
1151 : : }
|