Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020-2021 HiSilicon Limited.
3 : : */
4 : :
5 : : #include <rte_malloc.h>
6 : :
7 : : #include "hns3_common.h"
8 : : #include "hns3_dcb.h"
9 : : #include "hns3_logs.h"
10 : : #include "hns3_tm.h"
11 : :
12 : : static inline uint32_t
13 : 0 : hns3_tm_max_tx_queues_get(struct rte_eth_dev *dev)
14 : : {
15 : : /*
16 : : * This API will called in pci device probe stage, we can't call
17 : : * rte_eth_dev_info_get to get max_tx_queues (due to rte_eth_devices
18 : : * not setup), so we call the hns3_dev_infos_get.
19 : : */
20 : : struct rte_eth_dev_info dev_info;
21 : :
22 : : memset(&dev_info, 0, sizeof(dev_info));
23 : 0 : (void)hns3_dev_infos_get(dev, &dev_info);
24 : 0 : return RTE_MIN(dev_info.max_tx_queues, RTE_MAX_QUEUES_PER_PORT);
25 : : }
26 : :
27 : : void
28 : 0 : hns3_tm_conf_init(struct rte_eth_dev *dev)
29 : : {
30 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
31 : : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
32 : 0 : uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
33 : :
34 [ # # ]: 0 : if (!hns3_dev_get_support(hw, TM))
35 : : return;
36 : :
37 : 0 : pf->tm_conf.nb_leaf_nodes_max = max_tx_queues;
38 : 0 : pf->tm_conf.nb_nodes_max = 1 + HNS3_MAX_TC_NUM + max_tx_queues;
39 : 0 : pf->tm_conf.nb_shaper_profile_max = 1 + HNS3_MAX_TC_NUM;
40 : :
41 : 0 : TAILQ_INIT(&pf->tm_conf.shaper_profile_list);
42 : 0 : pf->tm_conf.nb_shaper_profile = 0;
43 : :
44 : 0 : pf->tm_conf.root = NULL;
45 : 0 : TAILQ_INIT(&pf->tm_conf.tc_list);
46 : 0 : TAILQ_INIT(&pf->tm_conf.queue_list);
47 : 0 : pf->tm_conf.nb_tc_node = 0;
48 : 0 : pf->tm_conf.nb_queue_node = 0;
49 : :
50 : 0 : pf->tm_conf.committed = false;
51 : : }
52 : :
53 : : void
54 : 0 : hns3_tm_conf_uninit(struct rte_eth_dev *dev)
55 : : {
56 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
57 : : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
58 : : struct hns3_tm_shaper_profile *shaper_profile;
59 : : struct hns3_tm_node *tm_node;
60 : :
61 [ # # ]: 0 : if (!hns3_dev_get_support(hw, TM))
62 : : return;
63 : :
64 [ # # ]: 0 : if (pf->tm_conf.nb_queue_node > 0) {
65 [ # # ]: 0 : while ((tm_node = TAILQ_FIRST(&pf->tm_conf.queue_list))) {
66 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.queue_list, tm_node, node);
67 : 0 : rte_free(tm_node);
68 : : }
69 : 0 : pf->tm_conf.nb_queue_node = 0;
70 : : }
71 : :
72 [ # # ]: 0 : if (pf->tm_conf.nb_tc_node > 0) {
73 [ # # ]: 0 : while ((tm_node = TAILQ_FIRST(&pf->tm_conf.tc_list))) {
74 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.tc_list, tm_node, node);
75 : 0 : rte_free(tm_node);
76 : : }
77 : 0 : pf->tm_conf.nb_tc_node = 0;
78 : : }
79 : :
80 [ # # ]: 0 : if (pf->tm_conf.root != NULL) {
81 : 0 : rte_free(pf->tm_conf.root);
82 : 0 : pf->tm_conf.root = NULL;
83 : : }
84 : :
85 [ # # ]: 0 : if (pf->tm_conf.nb_shaper_profile > 0) {
86 [ # # ]: 0 : while ((shaper_profile =
87 : : TAILQ_FIRST(&pf->tm_conf.shaper_profile_list))) {
88 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list,
89 : : shaper_profile, node);
90 : 0 : rte_free(shaper_profile);
91 : : }
92 : 0 : pf->tm_conf.nb_shaper_profile = 0;
93 : : }
94 : :
95 : 0 : pf->tm_conf.nb_leaf_nodes_max = 0;
96 : 0 : pf->tm_conf.nb_nodes_max = 0;
97 : 0 : pf->tm_conf.nb_shaper_profile_max = 0;
98 : : }
99 : :
100 : : static inline uint64_t
101 : : hns3_tm_rate_convert_firmware2tm(uint32_t firmware_rate)
102 : : {
103 : : #define FIRMWARE_TO_TM_RATE_SCALE 125000
104 : : /* tm rate unit is Bps, firmware rate is Mbps */
105 : 0 : return ((uint64_t)firmware_rate) * FIRMWARE_TO_TM_RATE_SCALE;
106 : : }
107 : :
108 : : static inline uint32_t
109 : : hns3_tm_rate_convert_tm2firmware(uint64_t tm_rate)
110 : : {
111 : : #define TM_TO_FIRMWARE_RATE_SCALE 125000
112 : : /* tm rate unit is Bps, firmware rate is Mbps */
113 : 0 : return (uint32_t)(tm_rate / TM_TO_FIRMWARE_RATE_SCALE);
114 : : }
115 : :
116 : : static int
117 : 0 : hns3_tm_capabilities_get(struct rte_eth_dev *dev,
118 : : struct rte_tm_capabilities *cap,
119 : : struct rte_tm_error *error)
120 : : {
121 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
122 : 0 : uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
123 : :
124 [ # # ]: 0 : if (cap == NULL || error == NULL)
125 : : return -EINVAL;
126 : :
127 : 0 : error->type = RTE_TM_ERROR_TYPE_NONE;
128 : :
129 : : memset(cap, 0, sizeof(struct rte_tm_capabilities));
130 : :
131 : 0 : cap->n_nodes_max = 1 + HNS3_MAX_TC_NUM + max_tx_queues;
132 : 0 : cap->n_levels_max = HNS3_TM_NODE_LEVEL_MAX;
133 : 0 : cap->non_leaf_nodes_identical = 1;
134 : 0 : cap->leaf_nodes_identical = 1;
135 : 0 : cap->shaper_n_max = 1 + HNS3_MAX_TC_NUM;
136 : 0 : cap->shaper_private_n_max = 1 + HNS3_MAX_TC_NUM;
137 : 0 : cap->shaper_private_rate_max =
138 : 0 : hns3_tm_rate_convert_firmware2tm(hw->max_tm_rate);
139 : :
140 : 0 : cap->sched_n_children_max = max_tx_queues;
141 : 0 : cap->sched_sp_n_priorities_max = 1;
142 : 0 : cap->sched_wfq_weight_max = 1;
143 : :
144 : 0 : cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
145 : 0 : cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
146 : :
147 : 0 : return 0;
148 : : }
149 : :
150 : : static struct hns3_tm_shaper_profile *
151 : : hns3_tm_shaper_profile_search(struct rte_eth_dev *dev,
152 : : uint32_t shaper_profile_id)
153 : : {
154 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
155 : : struct hns3_shaper_profile_list *shaper_profile_list =
156 : : &pf->tm_conf.shaper_profile_list;
157 : : struct hns3_tm_shaper_profile *shaper_profile;
158 : :
159 [ # # # # : 0 : TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
# # # # #
# # # ]
160 [ # # # # : 0 : if (shaper_profile_id == shaper_profile->shaper_profile_id)
# # # # #
# # # ]
161 : : return shaper_profile;
162 : : }
163 : :
164 : : return NULL;
165 : : }
166 : :
167 : : static int
168 : 0 : hns3_tm_shaper_profile_param_check(struct rte_eth_dev *dev,
169 : : const struct rte_tm_shaper_params *profile,
170 : : struct rte_tm_error *error)
171 : : {
172 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
173 : :
174 [ # # ]: 0 : if (profile->committed.rate) {
175 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE;
176 : 0 : error->message = "committed rate not supported";
177 : 0 : return -EINVAL;
178 : : }
179 : :
180 [ # # ]: 0 : if (profile->committed.size) {
181 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
182 : 0 : error->message = "committed bucket size not supported";
183 : 0 : return -EINVAL;
184 : : }
185 : :
186 : 0 : if (profile->peak.rate >
187 [ # # ]: 0 : hns3_tm_rate_convert_firmware2tm(hw->max_tm_rate)) {
188 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE;
189 : 0 : error->message = "peak rate too large";
190 : 0 : return -EINVAL;
191 : : }
192 : :
193 [ # # ]: 0 : if (profile->peak.rate < hns3_tm_rate_convert_firmware2tm(1)) {
194 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE;
195 : 0 : error->message = "peak rate must be at least 1Mbps";
196 : 0 : return -EINVAL;
197 : : }
198 : :
199 [ # # ]: 0 : if (profile->peak.size) {
200 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
201 : 0 : error->message = "peak bucket size not supported";
202 : 0 : return -EINVAL;
203 : : }
204 : :
205 [ # # ]: 0 : if (profile->pkt_length_adjust) {
206 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
207 : 0 : error->message = "packet length adjustment not supported";
208 : 0 : return -EINVAL;
209 : : }
210 : :
211 [ # # ]: 0 : if (profile->packet_mode) {
212 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PACKET_MODE;
213 : 0 : error->message = "packet mode not supported";
214 : 0 : return -EINVAL;
215 : : }
216 : :
217 : : return 0;
218 : : }
219 : :
220 : : static int
221 : 0 : hns3_tm_shaper_profile_add(struct rte_eth_dev *dev,
222 : : uint32_t shaper_profile_id,
223 : : const struct rte_tm_shaper_params *profile,
224 : : struct rte_tm_error *error)
225 : : {
226 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
227 : : struct hns3_tm_shaper_profile *shaper_profile;
228 : : int ret;
229 : :
230 [ # # ]: 0 : if (profile == NULL || error == NULL)
231 : : return -EINVAL;
232 : :
233 : 0 : if (pf->tm_conf.nb_shaper_profile >=
234 [ # # ]: 0 : pf->tm_conf.nb_shaper_profile_max) {
235 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
236 : 0 : error->message = "too much profiles";
237 : 0 : return -EINVAL;
238 : : }
239 : :
240 : 0 : ret = hns3_tm_shaper_profile_param_check(dev, profile, error);
241 [ # # ]: 0 : if (ret)
242 : : return ret;
243 : :
244 : : shaper_profile = hns3_tm_shaper_profile_search(dev, shaper_profile_id);
245 [ # # ]: 0 : if (shaper_profile) {
246 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
247 : 0 : error->message = "profile ID exist";
248 : 0 : return -EINVAL;
249 : : }
250 : :
251 : 0 : shaper_profile = rte_zmalloc("hns3_tm_shaper_profile",
252 : : sizeof(struct hns3_tm_shaper_profile),
253 : : 0);
254 [ # # ]: 0 : if (shaper_profile == NULL)
255 : : return -ENOMEM;
256 : :
257 : 0 : shaper_profile->shaper_profile_id = shaper_profile_id;
258 : 0 : memcpy(&shaper_profile->profile, profile,
259 : : sizeof(struct rte_tm_shaper_params));
260 : 0 : TAILQ_INSERT_TAIL(&pf->tm_conf.shaper_profile_list,
261 : : shaper_profile, node);
262 : 0 : pf->tm_conf.nb_shaper_profile++;
263 : :
264 : 0 : return 0;
265 : : }
266 : :
267 : : static int
268 : 0 : hns3_tm_shaper_profile_del(struct rte_eth_dev *dev,
269 : : uint32_t shaper_profile_id,
270 : : struct rte_tm_error *error)
271 : : {
272 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
273 : : struct hns3_tm_shaper_profile *shaper_profile;
274 : :
275 [ # # ]: 0 : if (error == NULL)
276 : : return -EINVAL;
277 : :
278 : : shaper_profile = hns3_tm_shaper_profile_search(dev, shaper_profile_id);
279 [ # # ]: 0 : if (shaper_profile == NULL) {
280 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
281 : 0 : error->message = "profile ID not exist";
282 : 0 : return -EINVAL;
283 : : }
284 : :
285 [ # # ]: 0 : if (shaper_profile->reference_count) {
286 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
287 : 0 : error->message = "profile in use";
288 : 0 : return -EINVAL;
289 : : }
290 : :
291 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.shaper_profile_list, shaper_profile, node);
292 : 0 : rte_free(shaper_profile);
293 : 0 : pf->tm_conf.nb_shaper_profile--;
294 : :
295 : 0 : return 0;
296 : : }
297 : :
298 : : static struct hns3_tm_node *
299 : 0 : hns3_tm_node_search(struct rte_eth_dev *dev,
300 : : uint32_t node_id,
301 : : enum hns3_tm_node_type *node_type)
302 : : {
303 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
304 : : struct hns3_tm_node_list *queue_list = &pf->tm_conf.queue_list;
305 : : struct hns3_tm_node_list *tc_list = &pf->tm_conf.tc_list;
306 : : struct hns3_tm_node *tm_node;
307 : :
308 [ # # # # ]: 0 : if (pf->tm_conf.root && pf->tm_conf.root->id == node_id) {
309 : 0 : *node_type = HNS3_TM_NODE_TYPE_PORT;
310 : 0 : return pf->tm_conf.root;
311 : : }
312 : :
313 [ # # ]: 0 : TAILQ_FOREACH(tm_node, tc_list, node) {
314 [ # # ]: 0 : if (tm_node->id == node_id) {
315 : 0 : *node_type = HNS3_TM_NODE_TYPE_TC;
316 : 0 : return tm_node;
317 : : }
318 : : }
319 : :
320 [ # # ]: 0 : TAILQ_FOREACH(tm_node, queue_list, node) {
321 [ # # ]: 0 : if (tm_node->id == node_id) {
322 : 0 : *node_type = HNS3_TM_NODE_TYPE_QUEUE;
323 : 0 : return tm_node;
324 : : }
325 : : }
326 : :
327 : : return NULL;
328 : : }
329 : :
330 : : static int
331 : 0 : hns3_tm_nonleaf_node_param_check(struct rte_eth_dev *dev,
332 : : const struct rte_tm_node_params *params,
333 : : struct rte_tm_error *error)
334 : : {
335 : : struct hns3_tm_shaper_profile *shaper_profile;
336 : :
337 [ # # ]: 0 : if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
338 : : shaper_profile = hns3_tm_shaper_profile_search(dev,
339 : : params->shaper_profile_id);
340 [ # # ]: 0 : if (shaper_profile == NULL) {
341 : 0 : error->type =
342 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
343 : 0 : error->message = "shaper profile not exist";
344 : 0 : return -EINVAL;
345 : : }
346 : : }
347 : :
348 [ # # ]: 0 : if (params->nonleaf.wfq_weight_mode) {
349 : 0 : error->type =
350 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
351 : 0 : error->message = "WFQ not supported";
352 : 0 : return -EINVAL;
353 : : }
354 : :
355 [ # # ]: 0 : if (params->nonleaf.n_sp_priorities != 1) {
356 : 0 : error->type =
357 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
358 : 0 : error->message = "SP priority not supported";
359 : 0 : return -EINVAL;
360 : : }
361 : :
362 : : return 0;
363 : : }
364 : :
365 : : static int
366 : : hns3_tm_leaf_node_param_check(struct rte_eth_dev *dev __rte_unused,
367 : : const struct rte_tm_node_params *params,
368 : : struct rte_tm_error *error)
369 : :
370 : : {
371 [ # # ]: 0 : if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
372 : 0 : error->type =
373 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
374 : 0 : error->message = "shaper not supported";
375 : 0 : return -EINVAL;
376 : : }
377 : :
378 [ # # ]: 0 : if (params->leaf.cman != RTE_TM_CMAN_TAIL_DROP) {
379 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
380 : 0 : error->message = "congestion management not supported";
381 : 0 : return -EINVAL;
382 : : }
383 : :
384 [ # # ]: 0 : if (params->leaf.wred.wred_profile_id != RTE_TM_WRED_PROFILE_ID_NONE) {
385 : 0 : error->type =
386 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
387 : 0 : error->message = "WRED not supported";
388 : 0 : return -EINVAL;
389 : : }
390 : :
391 [ # # ]: 0 : if (params->leaf.wred.shared_wred_context_id) {
392 : 0 : error->type =
393 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
394 : 0 : error->message = "WRED not supported";
395 : 0 : return -EINVAL;
396 : : }
397 : :
398 [ # # ]: 0 : if (params->leaf.wred.n_shared_wred_contexts) {
399 : 0 : error->type =
400 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
401 : 0 : error->message = "WRED not supported";
402 : 0 : return -EINVAL;
403 : : }
404 : :
405 : : return 0;
406 : : }
407 : :
408 : : static int
409 : 0 : hns3_tm_node_param_check(struct rte_eth_dev *dev, uint32_t node_id,
410 : : uint32_t priority, uint32_t weight,
411 : : const struct rte_tm_node_params *params,
412 : : struct rte_tm_error *error)
413 : : {
414 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
415 : 0 : enum hns3_tm_node_type node_type = HNS3_TM_NODE_TYPE_MAX;
416 : :
417 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
418 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
419 : 0 : error->message = "invalid node id";
420 : 0 : return -EINVAL;
421 : : }
422 : :
423 [ # # ]: 0 : if (hns3_tm_node_search(dev, node_id, &node_type)) {
424 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
425 : 0 : error->message = "node id already used";
426 : 0 : return -EINVAL;
427 : : }
428 : :
429 [ # # ]: 0 : if (priority) {
430 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
431 : 0 : error->message = "priority should be 0";
432 : 0 : return -EINVAL;
433 : : }
434 : :
435 [ # # ]: 0 : if (weight != 1) {
436 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
437 : 0 : error->message = "weight must be 1";
438 : 0 : return -EINVAL;
439 : : }
440 : :
441 [ # # ]: 0 : if (params->shared_shaper_id) {
442 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
443 : 0 : error->message = "shared shaper not supported";
444 : 0 : return -EINVAL;
445 : : }
446 [ # # ]: 0 : if (params->n_shared_shapers) {
447 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
448 : 0 : error->message = "shared shaper not supported";
449 : 0 : return -EINVAL;
450 : : }
451 : :
452 [ # # ]: 0 : if (node_id >= pf->tm_conf.nb_leaf_nodes_max)
453 : 0 : return hns3_tm_nonleaf_node_param_check(dev, params, error);
454 : : else
455 : 0 : return hns3_tm_leaf_node_param_check(dev, params, error);
456 : : }
457 : :
458 : : static int
459 : 0 : hns3_tm_port_node_add(struct rte_eth_dev *dev, uint32_t node_id,
460 : : uint32_t level_id, const struct rte_tm_node_params *params,
461 : : struct rte_tm_error *error)
462 : : {
463 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
464 : : struct hns3_tm_node *tm_node;
465 : :
466 [ # # ]: 0 : if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
467 : : level_id != HNS3_TM_NODE_LEVEL_PORT) {
468 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
469 : 0 : error->message = "wrong level";
470 : 0 : return -EINVAL;
471 : : }
472 : :
473 [ # # ]: 0 : if (node_id != pf->tm_conf.nb_nodes_max - 1) {
474 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
475 : 0 : error->message = "invalid port node ID";
476 : 0 : return -EINVAL;
477 : : }
478 : :
479 [ # # ]: 0 : if (pf->tm_conf.root) {
480 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
481 : 0 : error->message = "already have a root";
482 : 0 : return -EINVAL;
483 : : }
484 : :
485 : 0 : tm_node = rte_zmalloc("hns3_tm_node", sizeof(struct hns3_tm_node), 0);
486 [ # # ]: 0 : if (tm_node == NULL)
487 : : return -ENOMEM;
488 : :
489 : 0 : tm_node->id = node_id;
490 : 0 : tm_node->reference_count = 0;
491 : 0 : tm_node->parent = NULL;
492 : 0 : tm_node->shaper_profile = hns3_tm_shaper_profile_search(dev,
493 : 0 : params->shaper_profile_id);
494 [ # # ]: 0 : memcpy(&tm_node->params, params, sizeof(struct rte_tm_node_params));
495 : 0 : pf->tm_conf.root = tm_node;
496 : :
497 [ # # ]: 0 : if (tm_node->shaper_profile)
498 : 0 : tm_node->shaper_profile->reference_count++;
499 : :
500 : : return 0;
501 : : }
502 : :
503 : : static int
504 : 0 : hns3_tm_tc_node_add(struct rte_eth_dev *dev, uint32_t node_id,
505 : : uint32_t level_id, struct hns3_tm_node *parent_node,
506 : : const struct rte_tm_node_params *params,
507 : : struct rte_tm_error *error)
508 : : {
509 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
510 : : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
511 : : struct hns3_tm_node *tm_node;
512 : :
513 : 0 : if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
514 [ # # ]: 0 : level_id != HNS3_TM_NODE_LEVEL_TC) {
515 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
516 : 0 : error->message = "wrong level";
517 : 0 : return -EINVAL;
518 : : }
519 : :
520 [ # # ]: 0 : if (node_id >= pf->tm_conf.nb_nodes_max - 1 ||
521 [ # # ]: 0 : node_id < pf->tm_conf.nb_leaf_nodes_max ||
522 [ # # ]: 0 : hns3_tm_calc_node_tc_no(&pf->tm_conf, node_id) >= hw->num_tc) {
523 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
524 : 0 : error->message = "invalid tc node ID";
525 : 0 : return -EINVAL;
526 : : }
527 : :
528 [ # # ]: 0 : if (pf->tm_conf.nb_tc_node >= hw->num_tc) {
529 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
530 : 0 : error->message = "too many TCs";
531 : 0 : return -EINVAL;
532 : : }
533 : :
534 : 0 : tm_node = rte_zmalloc("hns3_tm_node", sizeof(struct hns3_tm_node), 0);
535 [ # # ]: 0 : if (tm_node == NULL)
536 : : return -ENOMEM;
537 : :
538 : 0 : tm_node->id = node_id;
539 : 0 : tm_node->reference_count = 0;
540 : 0 : tm_node->parent = parent_node;
541 : 0 : tm_node->shaper_profile = hns3_tm_shaper_profile_search(dev,
542 : 0 : params->shaper_profile_id);
543 [ # # ]: 0 : memcpy(&tm_node->params, params, sizeof(struct rte_tm_node_params));
544 : 0 : TAILQ_INSERT_TAIL(&pf->tm_conf.tc_list, tm_node, node);
545 : 0 : pf->tm_conf.nb_tc_node++;
546 : 0 : tm_node->parent->reference_count++;
547 : :
548 [ # # ]: 0 : if (tm_node->shaper_profile)
549 : 0 : tm_node->shaper_profile->reference_count++;
550 : :
551 : : return 0;
552 : : }
553 : :
554 : : static int
555 : 0 : hns3_tm_queue_node_add(struct rte_eth_dev *dev, uint32_t node_id,
556 : : uint32_t level_id, struct hns3_tm_node *parent_node,
557 : : const struct rte_tm_node_params *params,
558 : : struct rte_tm_error *error)
559 : : {
560 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
561 : : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
562 : : struct hns3_tm_node *tm_node;
563 : :
564 : 0 : if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
565 [ # # ]: 0 : level_id != HNS3_TM_NODE_LEVEL_QUEUE) {
566 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
567 : 0 : error->message = "wrong level";
568 : 0 : return -EINVAL;
569 : : }
570 : :
571 : : /* note: dev->data->nb_tx_queues <= max_tx_queues */
572 [ # # ]: 0 : if (node_id >= dev->data->nb_tx_queues) {
573 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
574 : 0 : error->message = "invalid queue node ID";
575 : 0 : return -EINVAL;
576 : : }
577 : :
578 [ # # ]: 0 : if (hns3_txq_mapped_tc_get(hw, node_id) !=
579 [ # # ]: 0 : hns3_tm_calc_node_tc_no(&pf->tm_conf, parent_node->id)) {
580 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
581 : 0 : error->message = "queue's TC not match parent's TC";
582 : 0 : return -EINVAL;
583 : : }
584 : :
585 : 0 : tm_node = rte_zmalloc("hns3_tm_node", sizeof(struct hns3_tm_node), 0);
586 [ # # ]: 0 : if (tm_node == NULL)
587 : : return -ENOMEM;
588 : :
589 : 0 : tm_node->id = node_id;
590 : 0 : tm_node->reference_count = 0;
591 : 0 : tm_node->parent = parent_node;
592 : 0 : memcpy(&tm_node->params, params, sizeof(struct rte_tm_node_params));
593 : 0 : TAILQ_INSERT_TAIL(&pf->tm_conf.queue_list, tm_node, node);
594 : 0 : pf->tm_conf.nb_queue_node++;
595 : 0 : tm_node->parent->reference_count++;
596 : :
597 : 0 : return 0;
598 : : }
599 : :
600 : : static int
601 : 0 : hns3_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,
602 : : uint32_t parent_node_id, uint32_t priority,
603 : : uint32_t weight, uint32_t level_id,
604 : : const struct rte_tm_node_params *params,
605 : : struct rte_tm_error *error)
606 : : {
607 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
608 : 0 : enum hns3_tm_node_type parent_node_type = HNS3_TM_NODE_TYPE_MAX;
609 : : struct hns3_tm_node *parent_node;
610 : : int ret;
611 : :
612 [ # # ]: 0 : if (params == NULL || error == NULL)
613 : : return -EINVAL;
614 : :
615 [ # # ]: 0 : if (pf->tm_conf.committed) {
616 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
617 : 0 : error->message = "already committed";
618 : 0 : return -EINVAL;
619 : : }
620 : :
621 : 0 : ret = hns3_tm_node_param_check(dev, node_id, priority, weight,
622 : : params, error);
623 [ # # ]: 0 : if (ret)
624 : : return ret;
625 : :
626 : : /* root node who don't have a parent */
627 [ # # ]: 0 : if (parent_node_id == RTE_TM_NODE_ID_NULL)
628 : 0 : return hns3_tm_port_node_add(dev, node_id, level_id,
629 : : params, error);
630 : :
631 : 0 : parent_node = hns3_tm_node_search(dev, parent_node_id,
632 : : &parent_node_type);
633 [ # # ]: 0 : if (parent_node == NULL) {
634 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
635 : 0 : error->message = "parent not exist";
636 : 0 : return -EINVAL;
637 : : }
638 : :
639 [ # # ]: 0 : if (parent_node_type != HNS3_TM_NODE_TYPE_PORT &&
640 : : parent_node_type != HNS3_TM_NODE_TYPE_TC) {
641 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
642 : 0 : error->message = "parent is not port or TC";
643 : 0 : return -EINVAL;
644 : : }
645 : :
646 [ # # ]: 0 : if (parent_node_type == HNS3_TM_NODE_TYPE_PORT)
647 : 0 : return hns3_tm_tc_node_add(dev, node_id, level_id,
648 : : parent_node, params, error);
649 : : else
650 : 0 : return hns3_tm_queue_node_add(dev, node_id, level_id,
651 : : parent_node, params, error);
652 : : }
653 : :
654 : : static void
655 : 0 : hns3_tm_node_do_delete(struct hns3_pf *pf,
656 : : enum hns3_tm_node_type node_type,
657 : : struct hns3_tm_node *tm_node)
658 : : {
659 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_PORT) {
660 [ # # ]: 0 : if (tm_node->shaper_profile)
661 : 0 : tm_node->shaper_profile->reference_count--;
662 : 0 : rte_free(tm_node);
663 : 0 : pf->tm_conf.root = NULL;
664 : 0 : return;
665 : : }
666 : :
667 [ # # ]: 0 : if (tm_node->shaper_profile)
668 : 0 : tm_node->shaper_profile->reference_count--;
669 : 0 : tm_node->parent->reference_count--;
670 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_TC) {
671 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.tc_list, tm_node, node);
672 : 0 : pf->tm_conf.nb_tc_node--;
673 : : } else {
674 [ # # ]: 0 : TAILQ_REMOVE(&pf->tm_conf.queue_list, tm_node, node);
675 : 0 : pf->tm_conf.nb_queue_node--;
676 : : }
677 : 0 : rte_free(tm_node);
678 : : }
679 : :
680 : : static int
681 : 0 : hns3_tm_node_delete(struct rte_eth_dev *dev,
682 : : uint32_t node_id,
683 : : struct rte_tm_error *error)
684 : : {
685 : 0 : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
686 : 0 : enum hns3_tm_node_type node_type = HNS3_TM_NODE_TYPE_MAX;
687 : : struct hns3_tm_node *tm_node;
688 : :
689 [ # # ]: 0 : if (error == NULL)
690 : : return -EINVAL;
691 : :
692 [ # # ]: 0 : if (pf->tm_conf.committed) {
693 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
694 : 0 : error->message = "already committed";
695 : 0 : return -EINVAL;
696 : : }
697 : :
698 : 0 : tm_node = hns3_tm_node_search(dev, node_id, &node_type);
699 [ # # ]: 0 : if (tm_node == NULL) {
700 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
701 : 0 : error->message = "no such node";
702 : 0 : return -EINVAL;
703 : : }
704 : :
705 [ # # ]: 0 : if (tm_node->reference_count) {
706 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
707 : 0 : error->message = "cannot delete a node which has children";
708 : 0 : return -EINVAL;
709 : : }
710 : :
711 : 0 : hns3_tm_node_do_delete(pf, node_type, tm_node);
712 : :
713 : 0 : return 0;
714 : : }
715 : :
716 : : static int
717 : 0 : hns3_tm_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
718 : : int *is_leaf, struct rte_tm_error *error)
719 : : {
720 : 0 : enum hns3_tm_node_type node_type = HNS3_TM_NODE_TYPE_MAX;
721 : : struct hns3_tm_node *tm_node;
722 : :
723 [ # # ]: 0 : if (is_leaf == NULL || error == NULL)
724 : : return -EINVAL;
725 : :
726 : 0 : tm_node = hns3_tm_node_search(dev, node_id, &node_type);
727 [ # # ]: 0 : if (tm_node == NULL) {
728 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
729 : 0 : error->message = "no such node";
730 : 0 : return -EINVAL;
731 : : }
732 : :
733 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_QUEUE)
734 : 0 : *is_leaf = true;
735 : : else
736 : 0 : *is_leaf = false;
737 : :
738 : : return 0;
739 : : }
740 : :
741 : : static void
742 : 0 : hns3_tm_nonleaf_level_capabilities_get(struct rte_eth_dev *dev,
743 : : uint32_t level_id,
744 : : struct rte_tm_level_capabilities *cap)
745 : : {
746 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
747 : 0 : uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
748 : :
749 [ # # ]: 0 : if (level_id == HNS3_TM_NODE_LEVEL_PORT) {
750 : 0 : cap->n_nodes_max = 1;
751 : 0 : cap->n_nodes_nonleaf_max = 1;
752 : 0 : cap->n_nodes_leaf_max = 0;
753 : : } else {
754 : 0 : cap->n_nodes_max = HNS3_MAX_TC_NUM;
755 : 0 : cap->n_nodes_nonleaf_max = HNS3_MAX_TC_NUM;
756 : 0 : cap->n_nodes_leaf_max = 0;
757 : : }
758 : :
759 : 0 : cap->non_leaf_nodes_identical = 1;
760 : 0 : cap->leaf_nodes_identical = 1;
761 : :
762 : 0 : cap->nonleaf.shaper_private_supported = true;
763 : 0 : cap->nonleaf.shaper_private_dual_rate_supported = false;
764 : 0 : cap->nonleaf.shaper_private_rate_min = 0;
765 : 0 : cap->nonleaf.shaper_private_rate_max =
766 : 0 : hns3_tm_rate_convert_firmware2tm(hw->max_tm_rate);
767 : 0 : cap->nonleaf.shaper_shared_n_max = 0;
768 [ # # ]: 0 : if (level_id == HNS3_TM_NODE_LEVEL_PORT)
769 : 0 : cap->nonleaf.sched_n_children_max = HNS3_MAX_TC_NUM;
770 : : else
771 : 0 : cap->nonleaf.sched_n_children_max = max_tx_queues;
772 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 1;
773 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
774 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
775 : 0 : cap->nonleaf.sched_wfq_weight_max = 1;
776 : 0 : cap->nonleaf.stats_mask = 0;
777 : 0 : }
778 : :
779 : : static void
780 : : hns3_tm_leaf_level_capabilities_get(struct rte_eth_dev *dev,
781 : : struct rte_tm_level_capabilities *cap)
782 : : {
783 : 0 : uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
784 : :
785 : 0 : cap->n_nodes_max = max_tx_queues;
786 : 0 : cap->n_nodes_nonleaf_max = 0;
787 : 0 : cap->n_nodes_leaf_max = max_tx_queues;
788 : :
789 : 0 : cap->non_leaf_nodes_identical = 1;
790 : 0 : cap->leaf_nodes_identical = 1;
791 : :
792 : 0 : cap->leaf.shaper_private_supported = false;
793 : 0 : cap->leaf.shaper_private_dual_rate_supported = false;
794 : 0 : cap->leaf.shaper_private_rate_min = 0;
795 : 0 : cap->leaf.shaper_private_rate_max = 0;
796 : 0 : cap->leaf.shaper_shared_n_max = 0;
797 : 0 : cap->leaf.cman_head_drop_supported = false;
798 : 0 : cap->leaf.cman_wred_context_private_supported = false;
799 : 0 : cap->leaf.cman_wred_context_shared_n_max = 0;
800 : 0 : cap->leaf.stats_mask = 0;
801 : 0 : }
802 : :
803 : : static int
804 : 0 : hns3_tm_level_capabilities_get(struct rte_eth_dev *dev,
805 : : uint32_t level_id,
806 : : struct rte_tm_level_capabilities *cap,
807 : : struct rte_tm_error *error)
808 : : {
809 [ # # ]: 0 : if (cap == NULL || error == NULL)
810 : : return -EINVAL;
811 : :
812 [ # # ]: 0 : if (level_id >= HNS3_TM_NODE_LEVEL_MAX) {
813 : 0 : error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
814 : 0 : error->message = "too deep level";
815 : 0 : return -EINVAL;
816 : : }
817 : :
818 : : memset(cap, 0, sizeof(struct rte_tm_level_capabilities));
819 : :
820 [ # # ]: 0 : if (level_id != HNS3_TM_NODE_LEVEL_QUEUE)
821 : 0 : hns3_tm_nonleaf_level_capabilities_get(dev, level_id, cap);
822 : : else
823 : : hns3_tm_leaf_level_capabilities_get(dev, cap);
824 : :
825 : : return 0;
826 : : }
827 : :
828 : : static void
829 : 0 : hns3_tm_nonleaf_node_capabilities_get(struct rte_eth_dev *dev,
830 : : enum hns3_tm_node_type node_type,
831 : : struct rte_tm_node_capabilities *cap)
832 : : {
833 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
834 : 0 : uint32_t max_tx_queues = hns3_tm_max_tx_queues_get(dev);
835 : :
836 : 0 : cap->shaper_private_supported = true;
837 : 0 : cap->shaper_private_dual_rate_supported = false;
838 : 0 : cap->shaper_private_rate_min = 0;
839 : 0 : cap->shaper_private_rate_max =
840 : 0 : hns3_tm_rate_convert_firmware2tm(hw->max_tm_rate);
841 : 0 : cap->shaper_shared_n_max = 0;
842 : :
843 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_PORT)
844 : 0 : cap->nonleaf.sched_n_children_max = HNS3_MAX_TC_NUM;
845 : : else
846 : 0 : cap->nonleaf.sched_n_children_max = max_tx_queues;
847 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 1;
848 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
849 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
850 : 0 : cap->nonleaf.sched_wfq_weight_max = 1;
851 : :
852 : 0 : cap->stats_mask = 0;
853 : 0 : }
854 : :
855 : : static void
856 : : hns3_tm_leaf_node_capabilities_get(struct rte_eth_dev *dev __rte_unused,
857 : : struct rte_tm_node_capabilities *cap)
858 : : {
859 : : cap->shaper_private_supported = false;
860 : : cap->shaper_private_dual_rate_supported = false;
861 : : cap->shaper_private_rate_min = 0;
862 : : cap->shaper_private_rate_max = 0;
863 : : cap->shaper_shared_n_max = 0;
864 : :
865 : : cap->leaf.cman_head_drop_supported = false;
866 : : cap->leaf.cman_wred_context_private_supported = false;
867 : : cap->leaf.cman_wred_context_shared_n_max = 0;
868 : :
869 : : cap->stats_mask = 0;
870 : : }
871 : :
872 : : static int
873 : 0 : hns3_tm_node_capabilities_get(struct rte_eth_dev *dev,
874 : : uint32_t node_id,
875 : : struct rte_tm_node_capabilities *cap,
876 : : struct rte_tm_error *error)
877 : : {
878 : : enum hns3_tm_node_type node_type;
879 : : struct hns3_tm_node *tm_node;
880 : :
881 [ # # ]: 0 : if (cap == NULL || error == NULL)
882 : : return -EINVAL;
883 : :
884 : 0 : tm_node = hns3_tm_node_search(dev, node_id, &node_type);
885 [ # # ]: 0 : if (tm_node == NULL) {
886 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
887 : 0 : error->message = "no such node";
888 : 0 : return -EINVAL;
889 : : }
890 : :
891 : : memset(cap, 0, sizeof(struct rte_tm_node_capabilities));
892 : :
893 [ # # ]: 0 : if (node_type != HNS3_TM_NODE_TYPE_QUEUE)
894 : 0 : hns3_tm_nonleaf_node_capabilities_get(dev, node_type, cap);
895 : : else
896 : : hns3_tm_leaf_node_capabilities_get(dev, cap);
897 : :
898 : : return 0;
899 : : }
900 : :
901 : : static int
902 : 0 : hns3_tm_config_port_rate(struct hns3_hw *hw,
903 : : struct hns3_tm_shaper_profile *shaper_profile)
904 : : {
905 : : struct hns3_port_limit_rate_cmd *cfg;
906 : : struct hns3_cmd_desc desc;
907 : : uint32_t firmware_rate;
908 : : uint64_t rate;
909 : : int ret;
910 : :
911 [ # # ]: 0 : if (shaper_profile) {
912 : 0 : rate = shaper_profile->profile.peak.rate;
913 : : firmware_rate = hns3_tm_rate_convert_tm2firmware(rate);
914 : : } else {
915 : 0 : firmware_rate = hw->max_tm_rate;
916 : : }
917 : :
918 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_PORT_LIMIT_RATE, false);
919 : : cfg = (struct hns3_port_limit_rate_cmd *)desc.data;
920 : 0 : cfg->speed = rte_cpu_to_le_32(firmware_rate);
921 : :
922 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
923 [ # # ]: 0 : if (ret)
924 : 0 : hns3_err(hw, "failed to config port rate, ret = %d", ret);
925 : :
926 : 0 : return ret;
927 : : }
928 : :
929 : : static int
930 : 0 : hns3_tm_config_tc_rate(struct hns3_hw *hw, uint8_t tc_no,
931 : : struct hns3_tm_shaper_profile *shaper_profile)
932 : : {
933 : : struct hns3_tc_limit_rate_cmd *cfg;
934 : : struct hns3_cmd_desc desc;
935 : : uint32_t firmware_rate;
936 : : uint64_t rate;
937 : : int ret;
938 : :
939 [ # # ]: 0 : if (shaper_profile) {
940 : 0 : rate = shaper_profile->profile.peak.rate;
941 : : firmware_rate = hns3_tm_rate_convert_tm2firmware(rate);
942 : : } else {
943 : 0 : firmware_rate = hw->dcb_info.tc_info[tc_no].bw_limit;
944 : : }
945 : :
946 : 0 : hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_TM_TC_LIMIT_RATE, false);
947 : : cfg = (struct hns3_tc_limit_rate_cmd *)desc.data;
948 : 0 : cfg->speed = rte_cpu_to_le_32(firmware_rate);
949 : 0 : cfg->tc_id = tc_no;
950 : :
951 : 0 : ret = hns3_cmd_send(hw, &desc, 1);
952 [ # # ]: 0 : if (ret)
953 : 0 : hns3_err(hw, "failed to config tc (%u) rate, ret = %d",
954 : : tc_no, ret);
955 : :
956 : 0 : return ret;
957 : : }
958 : :
959 : : static bool
960 : 0 : hns3_tm_configure_check(struct hns3_hw *hw, struct rte_tm_error *error)
961 : : {
962 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
963 : : struct hns3_tm_conf *tm_conf = &pf->tm_conf;
964 : : struct hns3_tm_node_list *tc_list = &tm_conf->tc_list;
965 : : struct hns3_tm_node_list *queue_list = &tm_conf->queue_list;
966 : : struct hns3_tm_node *tm_node;
967 : :
968 : : /* TC */
969 [ # # ]: 0 : TAILQ_FOREACH(tm_node, tc_list, node) {
970 [ # # ]: 0 : if (!tm_node->reference_count) {
971 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
972 : 0 : error->message = "TC without queue assigned";
973 : 0 : return false;
974 : : }
975 : :
976 [ # # ]: 0 : if (hns3_tm_calc_node_tc_no(tm_conf, tm_node->id) >=
977 [ # # ]: 0 : hw->num_tc) {
978 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
979 : 0 : error->message = "node's TC not exist";
980 : 0 : return false;
981 : : }
982 : : }
983 : :
984 : : /* Queue */
985 [ # # ]: 0 : TAILQ_FOREACH(tm_node, queue_list, node) {
986 [ # # ]: 0 : if (tm_node->id >= hw->data->nb_tx_queues) {
987 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
988 : 0 : error->message = "node's queue invalid";
989 : 0 : return false;
990 : : }
991 : :
992 [ # # ]: 0 : if (hns3_txq_mapped_tc_get(hw, tm_node->id) !=
993 [ # # ]: 0 : hns3_tm_calc_node_tc_no(tm_conf, tm_node->parent->id)) {
994 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
995 : 0 : error->message = "queue's TC not match parent's TC";
996 : 0 : return false;
997 : : }
998 : : }
999 : :
1000 : : return true;
1001 : : }
1002 : :
1003 : : static int
1004 : 0 : hns3_tm_hierarchy_do_commit(struct hns3_hw *hw,
1005 : : struct rte_tm_error *error)
1006 : : {
1007 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
1008 : : struct hns3_tm_node_list *tc_list = &pf->tm_conf.tc_list;
1009 : : struct hns3_tm_node *tm_node;
1010 : : uint8_t tc_no;
1011 : : int ret;
1012 : :
1013 : : /* port */
1014 : 0 : tm_node = pf->tm_conf.root;
1015 [ # # ]: 0 : if (tm_node->shaper_profile) {
1016 : 0 : ret = hns3_tm_config_port_rate(hw, tm_node->shaper_profile);
1017 [ # # ]: 0 : if (ret) {
1018 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1019 : 0 : error->message = "fail to set port peak rate";
1020 : 0 : return -EIO;
1021 : : }
1022 : : }
1023 : :
1024 : : /* TC */
1025 [ # # ]: 0 : TAILQ_FOREACH(tm_node, tc_list, node) {
1026 [ # # ]: 0 : if (tm_node->shaper_profile == NULL)
1027 : 0 : continue;
1028 : :
1029 [ # # ]: 0 : tc_no = hns3_tm_calc_node_tc_no(&pf->tm_conf, tm_node->id);
1030 : 0 : ret = hns3_tm_config_tc_rate(hw, tc_no,
1031 : : tm_node->shaper_profile);
1032 [ # # ]: 0 : if (ret) {
1033 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
1034 : 0 : error->message = "fail to set TC peak rate";
1035 : 0 : return -EIO;
1036 : : }
1037 : : }
1038 : :
1039 : : return 0;
1040 : : }
1041 : :
1042 : : static int
1043 : 0 : hns3_tm_hierarchy_commit(struct rte_eth_dev *dev,
1044 : : int clear_on_fail,
1045 : : struct rte_tm_error *error)
1046 : : {
1047 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1048 : : struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1049 : : int ret;
1050 : :
1051 [ # # ]: 0 : if (error == NULL)
1052 : : return -EINVAL;
1053 : :
1054 [ # # ]: 0 : if (rte_atomic_load_explicit(&hw->reset.resetting, rte_memory_order_relaxed)) {
1055 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1056 : 0 : error->message = "device is resetting";
1057 : : /* don't goto fail_clear, user may try later */
1058 : 0 : return -EBUSY;
1059 : : }
1060 : :
1061 [ # # ]: 0 : if (pf->tm_conf.root == NULL)
1062 : 0 : goto done;
1063 : :
1064 : : /* check configure before commit make sure key configure not violated */
1065 [ # # ]: 0 : if (!hns3_tm_configure_check(hw, error))
1066 : 0 : goto fail_clear;
1067 : :
1068 : 0 : ret = hns3_tm_hierarchy_do_commit(hw, error);
1069 [ # # ]: 0 : if (ret)
1070 : 0 : goto fail_clear;
1071 : :
1072 : 0 : done:
1073 : 0 : pf->tm_conf.committed = true;
1074 : 0 : return 0;
1075 : :
1076 : 0 : fail_clear:
1077 [ # # ]: 0 : if (clear_on_fail) {
1078 : 0 : hns3_tm_conf_uninit(dev);
1079 : 0 : hns3_tm_conf_init(dev);
1080 : : }
1081 : : return -EINVAL;
1082 : : }
1083 : :
1084 : : static int
1085 : 0 : hns3_tm_node_shaper_do_update(struct hns3_hw *hw,
1086 : : uint32_t node_id,
1087 : : enum hns3_tm_node_type node_type,
1088 : : struct hns3_tm_shaper_profile *shaper_profile,
1089 : : struct rte_tm_error *error)
1090 : : {
1091 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
1092 : : uint8_t tc_no;
1093 : : int ret;
1094 : :
1095 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_QUEUE) {
1096 [ # # ]: 0 : if (shaper_profile != NULL) {
1097 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
1098 : 0 : error->message = "queue node shaper not supported";
1099 : 0 : return -EINVAL;
1100 : : }
1101 : : return 0;
1102 : : }
1103 : :
1104 [ # # ]: 0 : if (!pf->tm_conf.committed)
1105 : : return 0;
1106 : :
1107 [ # # ]: 0 : if (node_type == HNS3_TM_NODE_TYPE_PORT) {
1108 : 0 : ret = hns3_tm_config_port_rate(hw, shaper_profile);
1109 [ # # ]: 0 : if (ret) {
1110 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1111 : 0 : error->message = "fail to update port peak rate";
1112 : : }
1113 : :
1114 : 0 : return ret;
1115 : : }
1116 : :
1117 : : /*
1118 : : * update TC's shaper
1119 : : */
1120 : : tc_no = hns3_tm_calc_node_tc_no(&pf->tm_conf, node_id);
1121 : 0 : ret = hns3_tm_config_tc_rate(hw, tc_no, shaper_profile);
1122 [ # # ]: 0 : if (ret) {
1123 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
1124 : 0 : error->message = "fail to update TC peak rate";
1125 : : }
1126 : :
1127 : : return ret;
1128 : : }
1129 : :
1130 : : static int
1131 : 0 : hns3_tm_node_shaper_update(struct rte_eth_dev *dev,
1132 : : uint32_t node_id,
1133 : : uint32_t shaper_profile_id,
1134 : : struct rte_tm_error *error)
1135 : : {
1136 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1137 : 0 : enum hns3_tm_node_type node_type = HNS3_TM_NODE_TYPE_MAX;
1138 : : struct hns3_tm_shaper_profile *profile = NULL;
1139 : : struct hns3_tm_node *tm_node;
1140 : :
1141 [ # # ]: 0 : if (error == NULL)
1142 : : return -EINVAL;
1143 : :
1144 [ # # ]: 0 : if (rte_atomic_load_explicit(&hw->reset.resetting, rte_memory_order_relaxed)) {
1145 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
1146 : 0 : error->message = "device is resetting";
1147 : 0 : return -EBUSY;
1148 : : }
1149 : :
1150 : 0 : tm_node = hns3_tm_node_search(dev, node_id, &node_type);
1151 [ # # ]: 0 : if (tm_node == NULL) {
1152 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
1153 : 0 : error->message = "no such node";
1154 : 0 : return -EINVAL;
1155 : : }
1156 : :
1157 [ # # ]: 0 : if (shaper_profile_id == tm_node->params.shaper_profile_id)
1158 : : return 0;
1159 : :
1160 [ # # ]: 0 : if (shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
1161 : : profile = hns3_tm_shaper_profile_search(dev, shaper_profile_id);
1162 [ # # ]: 0 : if (profile == NULL) {
1163 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
1164 : 0 : error->message = "profile ID not exist";
1165 : 0 : return -EINVAL;
1166 : : }
1167 : : }
1168 : :
1169 [ # # ]: 0 : if (hns3_tm_node_shaper_do_update(hw, node_id, node_type,
1170 : : profile, error))
1171 : : return -EINVAL;
1172 : :
1173 [ # # ]: 0 : if (tm_node->shaper_profile)
1174 : 0 : tm_node->shaper_profile->reference_count--;
1175 : 0 : tm_node->shaper_profile = profile;
1176 : 0 : tm_node->params.shaper_profile_id = shaper_profile_id;
1177 [ # # ]: 0 : if (profile != NULL)
1178 : 0 : profile->reference_count++;
1179 : :
1180 : : return 0;
1181 : : }
1182 : :
1183 : : static int
1184 : 0 : hns3_tm_capabilities_get_wrap(struct rte_eth_dev *dev,
1185 : : struct rte_tm_capabilities *cap,
1186 : : struct rte_tm_error *error)
1187 : : {
1188 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1189 : : int ret;
1190 : :
1191 : 0 : rte_spinlock_lock(&hw->lock);
1192 : 0 : ret = hns3_tm_capabilities_get(dev, cap, error);
1193 : : rte_spinlock_unlock(&hw->lock);
1194 : :
1195 : 0 : return ret;
1196 : : }
1197 : :
1198 : : static int
1199 : 0 : hns3_tm_shaper_profile_add_wrap(struct rte_eth_dev *dev,
1200 : : uint32_t shaper_profile_id,
1201 : : const struct rte_tm_shaper_params *profile,
1202 : : struct rte_tm_error *error)
1203 : : {
1204 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1205 : : int ret;
1206 : :
1207 : 0 : rte_spinlock_lock(&hw->lock);
1208 : 0 : ret = hns3_tm_shaper_profile_add(dev, shaper_profile_id, profile, error);
1209 : : rte_spinlock_unlock(&hw->lock);
1210 : :
1211 : 0 : return ret;
1212 : : }
1213 : :
1214 : : static int
1215 : 0 : hns3_tm_shaper_profile_del_wrap(struct rte_eth_dev *dev,
1216 : : uint32_t shaper_profile_id,
1217 : : struct rte_tm_error *error)
1218 : : {
1219 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1220 : : int ret;
1221 : :
1222 : 0 : rte_spinlock_lock(&hw->lock);
1223 : 0 : ret = hns3_tm_shaper_profile_del(dev, shaper_profile_id, error);
1224 : : rte_spinlock_unlock(&hw->lock);
1225 : :
1226 : 0 : return ret;
1227 : : }
1228 : :
1229 : : static int
1230 : 0 : hns3_tm_node_add_wrap(struct rte_eth_dev *dev, uint32_t node_id,
1231 : : uint32_t parent_node_id, uint32_t priority,
1232 : : uint32_t weight, uint32_t level_id,
1233 : : const struct rte_tm_node_params *params,
1234 : : struct rte_tm_error *error)
1235 : : {
1236 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1237 : : int ret;
1238 : :
1239 : 0 : rte_spinlock_lock(&hw->lock);
1240 : 0 : ret = hns3_tm_node_add(dev, node_id, parent_node_id, priority,
1241 : : weight, level_id, params, error);
1242 : : rte_spinlock_unlock(&hw->lock);
1243 : :
1244 : 0 : return ret;
1245 : : }
1246 : :
1247 : : static int
1248 : 0 : hns3_tm_node_delete_wrap(struct rte_eth_dev *dev,
1249 : : uint32_t node_id,
1250 : : struct rte_tm_error *error)
1251 : : {
1252 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1253 : : int ret;
1254 : :
1255 : 0 : rte_spinlock_lock(&hw->lock);
1256 : 0 : ret = hns3_tm_node_delete(dev, node_id, error);
1257 : : rte_spinlock_unlock(&hw->lock);
1258 : :
1259 : 0 : return ret;
1260 : : }
1261 : :
1262 : : static int
1263 : 0 : hns3_tm_node_type_get_wrap(struct rte_eth_dev *dev,
1264 : : uint32_t node_id,
1265 : : int *is_leaf,
1266 : : struct rte_tm_error *error)
1267 : : {
1268 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1269 : : int ret;
1270 : :
1271 : 0 : rte_spinlock_lock(&hw->lock);
1272 : 0 : ret = hns3_tm_node_type_get(dev, node_id, is_leaf, error);
1273 : : rte_spinlock_unlock(&hw->lock);
1274 : :
1275 : 0 : return ret;
1276 : : }
1277 : :
1278 : : static int
1279 : 0 : hns3_tm_level_capabilities_get_wrap(struct rte_eth_dev *dev,
1280 : : uint32_t level_id,
1281 : : struct rte_tm_level_capabilities *cap,
1282 : : struct rte_tm_error *error)
1283 : : {
1284 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1285 : : int ret;
1286 : :
1287 : 0 : rte_spinlock_lock(&hw->lock);
1288 : 0 : ret = hns3_tm_level_capabilities_get(dev, level_id, cap, error);
1289 : : rte_spinlock_unlock(&hw->lock);
1290 : :
1291 : 0 : return ret;
1292 : : }
1293 : :
1294 : : static int
1295 : 0 : hns3_tm_node_capabilities_get_wrap(struct rte_eth_dev *dev,
1296 : : uint32_t node_id,
1297 : : struct rte_tm_node_capabilities *cap,
1298 : : struct rte_tm_error *error)
1299 : : {
1300 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1301 : : int ret;
1302 : :
1303 : 0 : rte_spinlock_lock(&hw->lock);
1304 : 0 : ret = hns3_tm_node_capabilities_get(dev, node_id, cap, error);
1305 : : rte_spinlock_unlock(&hw->lock);
1306 : :
1307 : 0 : return ret;
1308 : : }
1309 : :
1310 : : static int
1311 : 0 : hns3_tm_hierarchy_commit_wrap(struct rte_eth_dev *dev,
1312 : : int clear_on_fail,
1313 : : struct rte_tm_error *error)
1314 : : {
1315 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1316 : : int ret;
1317 : :
1318 : 0 : rte_spinlock_lock(&hw->lock);
1319 : 0 : ret = hns3_tm_hierarchy_commit(dev, clear_on_fail, error);
1320 : : rte_spinlock_unlock(&hw->lock);
1321 : :
1322 : 0 : return ret;
1323 : : }
1324 : :
1325 : : static int
1326 : 0 : hns3_tm_node_shaper_update_wrap(struct rte_eth_dev *dev,
1327 : : uint32_t node_id,
1328 : : uint32_t shaper_profile_id,
1329 : : struct rte_tm_error *error)
1330 : : {
1331 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1332 : : int ret;
1333 : :
1334 : 0 : rte_spinlock_lock(&hw->lock);
1335 : 0 : ret = hns3_tm_node_shaper_update(dev, node_id,
1336 : : shaper_profile_id, error);
1337 : : rte_spinlock_unlock(&hw->lock);
1338 : :
1339 : 0 : return ret;
1340 : : }
1341 : :
1342 : : static const struct rte_tm_ops hns3_tm_ops = {
1343 : : .capabilities_get = hns3_tm_capabilities_get_wrap,
1344 : : .shaper_profile_add = hns3_tm_shaper_profile_add_wrap,
1345 : : .shaper_profile_delete = hns3_tm_shaper_profile_del_wrap,
1346 : : .node_add = hns3_tm_node_add_wrap,
1347 : : .node_delete = hns3_tm_node_delete_wrap,
1348 : : .node_type_get = hns3_tm_node_type_get_wrap,
1349 : : .level_capabilities_get = hns3_tm_level_capabilities_get_wrap,
1350 : : .node_capabilities_get = hns3_tm_node_capabilities_get_wrap,
1351 : : .hierarchy_commit = hns3_tm_hierarchy_commit_wrap,
1352 : : .node_shaper_update = hns3_tm_node_shaper_update_wrap,
1353 : : };
1354 : :
1355 : : int
1356 : 0 : hns3_tm_ops_get(struct rte_eth_dev *dev, void *arg)
1357 : : {
1358 : 0 : struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1359 : :
1360 [ # # ]: 0 : if (arg == NULL)
1361 : : return -EINVAL;
1362 : :
1363 [ # # ]: 0 : if (!hns3_dev_get_support(hw, TM))
1364 : : return -EOPNOTSUPP;
1365 : :
1366 : 0 : *(const void **)arg = &hns3_tm_ops;
1367 : :
1368 : 0 : return 0;
1369 : : }
1370 : :
1371 : : void
1372 : 0 : hns3_tm_dev_start_proc(struct hns3_hw *hw)
1373 : : {
1374 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
1375 : :
1376 [ # # ]: 0 : if (!hns3_dev_get_support(hw, TM))
1377 : : return;
1378 : :
1379 [ # # # # ]: 0 : if (pf->tm_conf.root && !pf->tm_conf.committed)
1380 : 0 : hns3_warn(hw,
1381 : : "please call hierarchy_commit() before starting the port.");
1382 : : }
1383 : :
1384 : : /*
1385 : : * We need clear tm_conf committed flag when device stop so that user can modify
1386 : : * tm configuration (e.g. add or delete node).
1387 : : *
1388 : : * If user don't call hierarchy commit when device start later, the Port/TC's
1389 : : * shaper rate still the same as previous committed.
1390 : : *
1391 : : * To avoid the above problem, we need recover Port/TC shaper rate when device
1392 : : * stop.
1393 : : */
1394 : : void
1395 : 0 : hns3_tm_dev_stop_proc(struct hns3_hw *hw)
1396 : : {
1397 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
1398 : : struct hns3_tm_node_list *tc_list = &pf->tm_conf.tc_list;
1399 : : struct hns3_tm_node *tm_node;
1400 : : uint8_t tc_no;
1401 : :
1402 [ # # ]: 0 : if (!pf->tm_conf.committed)
1403 : : return;
1404 : :
1405 : 0 : tm_node = pf->tm_conf.root;
1406 [ # # # # ]: 0 : if (tm_node != NULL && tm_node->shaper_profile)
1407 : 0 : (void)hns3_tm_config_port_rate(hw, NULL);
1408 : :
1409 [ # # ]: 0 : TAILQ_FOREACH(tm_node, tc_list, node) {
1410 [ # # ]: 0 : if (tm_node->shaper_profile == NULL)
1411 : 0 : continue;
1412 [ # # ]: 0 : tc_no = hns3_tm_calc_node_tc_no(&pf->tm_conf, tm_node->id);
1413 : 0 : (void)hns3_tm_config_tc_rate(hw, tc_no, NULL);
1414 : : }
1415 : :
1416 : 0 : pf->tm_conf.committed = false;
1417 : : }
1418 : :
1419 : : int
1420 : 0 : hns3_tm_conf_update(struct hns3_hw *hw)
1421 : : {
1422 : : struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
1423 : : struct rte_tm_error error;
1424 : :
1425 [ # # ]: 0 : if (!hns3_dev_get_support(hw, TM))
1426 : : return 0;
1427 : :
1428 [ # # # # ]: 0 : if (pf->tm_conf.root == NULL || !pf->tm_conf.committed)
1429 : : return 0;
1430 : :
1431 : : memset(&error, 0, sizeof(struct rte_tm_error));
1432 : 0 : return hns3_tm_hierarchy_do_commit(hw, &error);
1433 : : }
|