Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2017 Intel Corporation
3 : : */
4 : : #include <rte_tm_driver.h>
5 : :
6 : : #include "iavf.h"
7 : :
8 : : static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
9 : : __rte_unused int clear_on_fail,
10 : : __rte_unused struct rte_tm_error *error);
11 : : static int iavf_shaper_profile_add(struct rte_eth_dev *dev,
12 : : uint32_t shaper_profile_id,
13 : : const struct rte_tm_shaper_params *profile,
14 : : struct rte_tm_error *error);
15 : : static int iavf_shaper_profile_del(struct rte_eth_dev *dev,
16 : : uint32_t shaper_profile_id,
17 : : struct rte_tm_error *error);
18 : : static int iavf_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,
19 : : uint32_t parent_node_id, uint32_t priority,
20 : : uint32_t weight, uint32_t level_id,
21 : : const struct rte_tm_node_params *params,
22 : : struct rte_tm_error *error);
23 : : static int iavf_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
24 : : struct rte_tm_error *error);
25 : : static int iavf_tm_capabilities_get(struct rte_eth_dev *dev,
26 : : struct rte_tm_capabilities *cap,
27 : : struct rte_tm_error *error);
28 : : static int iavf_level_capabilities_get(struct rte_eth_dev *dev,
29 : : uint32_t level_id,
30 : : struct rte_tm_level_capabilities *cap,
31 : : struct rte_tm_error *error);
32 : : static int iavf_node_capabilities_get(struct rte_eth_dev *dev,
33 : : uint32_t node_id,
34 : : struct rte_tm_node_capabilities *cap,
35 : : struct rte_tm_error *error);
36 : : static int iavf_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
37 : : int *is_leaf, struct rte_tm_error *error);
38 : :
39 : : const struct rte_tm_ops iavf_tm_ops = {
40 : : .shaper_profile_add = iavf_shaper_profile_add,
41 : : .shaper_profile_delete = iavf_shaper_profile_del,
42 : : .node_add = iavf_tm_node_add,
43 : : .node_delete = iavf_tm_node_delete,
44 : : .capabilities_get = iavf_tm_capabilities_get,
45 : : .level_capabilities_get = iavf_level_capabilities_get,
46 : : .node_capabilities_get = iavf_node_capabilities_get,
47 : : .node_type_get = iavf_node_type_get,
48 : : .hierarchy_commit = iavf_hierarchy_commit,
49 : : };
50 : :
51 : : void
52 : 0 : iavf_tm_conf_init(struct rte_eth_dev *dev)
53 : : {
54 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
55 : :
56 : : /* initialize shaper profile list */
57 : 0 : TAILQ_INIT(&vf->tm_conf.shaper_profile_list);
58 : :
59 : : /* initialize node configuration */
60 : 0 : vf->tm_conf.root = NULL;
61 : 0 : TAILQ_INIT(&vf->tm_conf.tc_list);
62 : 0 : TAILQ_INIT(&vf->tm_conf.queue_list);
63 : 0 : vf->tm_conf.nb_tc_node = 0;
64 : 0 : vf->tm_conf.nb_queue_node = 0;
65 : 0 : vf->tm_conf.committed = false;
66 : 0 : }
67 : :
68 : : void
69 : 0 : iavf_tm_conf_uninit(struct rte_eth_dev *dev)
70 : : {
71 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
72 : : struct iavf_tm_shaper_profile *shaper_profile;
73 : : struct iavf_tm_node *tm_node;
74 : :
75 : : /* clear node configuration */
76 [ # # ]: 0 : while ((tm_node = TAILQ_FIRST(&vf->tm_conf.queue_list))) {
77 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.queue_list, tm_node, node);
78 : 0 : rte_free(tm_node);
79 : : }
80 : 0 : vf->tm_conf.nb_queue_node = 0;
81 [ # # ]: 0 : while ((tm_node = TAILQ_FIRST(&vf->tm_conf.tc_list))) {
82 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.tc_list, tm_node, node);
83 : 0 : rte_free(tm_node);
84 : : }
85 : 0 : vf->tm_conf.nb_tc_node = 0;
86 [ # # ]: 0 : if (vf->tm_conf.root) {
87 : 0 : rte_free(vf->tm_conf.root);
88 : 0 : vf->tm_conf.root = NULL;
89 : : }
90 : :
91 : : /* Remove all shaper profiles */
92 [ # # ]: 0 : while ((shaper_profile =
93 : : TAILQ_FIRST(&vf->tm_conf.shaper_profile_list))) {
94 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.shaper_profile_list,
95 : : shaper_profile, node);
96 : 0 : rte_free(shaper_profile);
97 : : }
98 : 0 : }
99 : :
100 : : static inline struct iavf_tm_node *
101 : 0 : iavf_tm_node_search(struct rte_eth_dev *dev,
102 : : uint32_t node_id, enum iavf_tm_node_type *node_type)
103 : : {
104 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
105 : : struct iavf_tm_node_list *tc_list = &vf->tm_conf.tc_list;
106 : : struct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;
107 : : struct iavf_tm_node *tm_node;
108 : :
109 [ # # # # ]: 0 : if (vf->tm_conf.root && vf->tm_conf.root->id == node_id) {
110 : 0 : *node_type = IAVF_TM_NODE_TYPE_PORT;
111 : 0 : return vf->tm_conf.root;
112 : : }
113 : :
114 [ # # ]: 0 : TAILQ_FOREACH(tm_node, tc_list, node) {
115 [ # # ]: 0 : if (tm_node->id == node_id) {
116 : 0 : *node_type = IAVF_TM_NODE_TYPE_TC;
117 : 0 : return tm_node;
118 : : }
119 : : }
120 : :
121 [ # # ]: 0 : TAILQ_FOREACH(tm_node, queue_list, node) {
122 [ # # ]: 0 : if (tm_node->id == node_id) {
123 : 0 : *node_type = IAVF_TM_NODE_TYPE_QUEUE;
124 : 0 : return tm_node;
125 : : }
126 : : }
127 : :
128 : : return NULL;
129 : : }
130 : :
131 : : static int
132 : 0 : iavf_node_param_check(struct iavf_info *vf, uint32_t node_id,
133 : : uint32_t priority, uint32_t weight,
134 : : const struct rte_tm_node_params *params,
135 : : struct rte_tm_error *error)
136 : : {
137 : : /* checked all the unsupported parameter */
138 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
139 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
140 : 0 : error->message = "invalid node id";
141 : 0 : return -EINVAL;
142 : : }
143 : :
144 [ # # ]: 0 : if (priority) {
145 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PRIORITY;
146 : 0 : error->message = "priority should be 0";
147 : 0 : return -EINVAL;
148 : : }
149 : :
150 [ # # ]: 0 : if (weight != 1) {
151 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_WEIGHT;
152 : 0 : error->message = "weight must be 1";
153 : 0 : return -EINVAL;
154 : : }
155 : :
156 : : /* not support shared shaper */
157 [ # # ]: 0 : if (params->shared_shaper_id) {
158 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID;
159 : 0 : error->message = "shared shaper not supported";
160 : 0 : return -EINVAL;
161 : : }
162 [ # # ]: 0 : if (params->n_shared_shapers) {
163 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS;
164 : 0 : error->message = "shared shaper not supported";
165 : 0 : return -EINVAL;
166 : : }
167 : :
168 : : /* for non-leaf node */
169 [ # # ]: 0 : if (node_id >= vf->num_queue_pairs) {
170 [ # # ]: 0 : if (params->nonleaf.wfq_weight_mode) {
171 : 0 : error->type =
172 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE;
173 : 0 : error->message = "WFQ not supported";
174 : 0 : return -EINVAL;
175 : : }
176 [ # # ]: 0 : if (params->nonleaf.n_sp_priorities != 1) {
177 : 0 : error->type =
178 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES;
179 : 0 : error->message = "SP priority not supported";
180 : 0 : return -EINVAL;
181 : : }
182 : :
183 : : return 0;
184 : : }
185 : :
186 : : /* for leaf node */
187 [ # # ]: 0 : if (params->leaf.cman) {
188 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN;
189 : 0 : error->message = "Congestion management not supported";
190 : 0 : return -EINVAL;
191 : : }
192 [ # # ]: 0 : if (params->leaf.wred.wred_profile_id !=
193 : : RTE_TM_WRED_PROFILE_ID_NONE) {
194 : 0 : error->type =
195 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID;
196 : 0 : error->message = "WRED not supported";
197 : 0 : return -EINVAL;
198 : : }
199 [ # # ]: 0 : if (params->leaf.wred.shared_wred_context_id) {
200 : 0 : error->type =
201 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID;
202 : 0 : error->message = "WRED not supported";
203 : 0 : return -EINVAL;
204 : : }
205 [ # # ]: 0 : if (params->leaf.wred.n_shared_wred_contexts) {
206 : 0 : error->type =
207 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS;
208 : 0 : error->message = "WRED not supported";
209 : 0 : return -EINVAL;
210 : : }
211 : :
212 : : return 0;
213 : : }
214 : :
215 : : static int
216 : 0 : iavf_node_type_get(struct rte_eth_dev *dev, uint32_t node_id,
217 : : int *is_leaf, struct rte_tm_error *error)
218 : : {
219 : 0 : enum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;
220 : : struct iavf_tm_node *tm_node;
221 : :
222 [ # # ]: 0 : if (!is_leaf || !error)
223 : : return -EINVAL;
224 : :
225 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
226 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
227 : 0 : error->message = "invalid node id";
228 : 0 : return -EINVAL;
229 : : }
230 : :
231 : : /* check if the node id exists */
232 : 0 : tm_node = iavf_tm_node_search(dev, node_id, &node_type);
233 [ # # ]: 0 : if (!tm_node) {
234 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
235 : 0 : error->message = "no such node";
236 : 0 : return -EINVAL;
237 : : }
238 : :
239 [ # # ]: 0 : if (node_type == IAVF_TM_NODE_TYPE_QUEUE)
240 : 0 : *is_leaf = true;
241 : : else
242 : 0 : *is_leaf = false;
243 : :
244 : : return 0;
245 : : }
246 : :
247 : : static inline struct iavf_tm_shaper_profile *
248 : : iavf_shaper_profile_search(struct rte_eth_dev *dev,
249 : : uint32_t shaper_profile_id)
250 : : {
251 : : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
252 : : struct iavf_shaper_profile_list *shaper_profile_list =
253 : : &vf->tm_conf.shaper_profile_list;
254 : : struct iavf_tm_shaper_profile *shaper_profile;
255 : :
256 [ # # # # : 0 : TAILQ_FOREACH(shaper_profile, shaper_profile_list, node) {
# # ]
257 [ # # # # : 0 : if (shaper_profile_id == shaper_profile->shaper_profile_id)
# # ]
258 : : return shaper_profile;
259 : : }
260 : :
261 : : return NULL;
262 : : }
263 : :
264 : : static int
265 : 0 : iavf_tm_node_add(struct rte_eth_dev *dev, uint32_t node_id,
266 : : uint32_t parent_node_id, uint32_t priority,
267 : : uint32_t weight, uint32_t level_id,
268 : : const struct rte_tm_node_params *params,
269 : : struct rte_tm_error *error)
270 : : {
271 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
272 : 0 : enum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;
273 : 0 : enum iavf_tm_node_type parent_node_type = IAVF_TM_NODE_TYPE_MAX;
274 : : struct iavf_tm_shaper_profile *shaper_profile = NULL;
275 : : struct iavf_tm_node *tm_node;
276 : : struct iavf_tm_node *parent_node;
277 : 0 : uint16_t tc_nb = vf->qos_cap->num_elem;
278 : : int ret;
279 : :
280 [ # # ]: 0 : if (!params || !error)
281 : : return -EINVAL;
282 : :
283 : : /* if already committed */
284 [ # # ]: 0 : if (vf->tm_conf.committed) {
285 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
286 : 0 : error->message = "already committed";
287 : 0 : return -EINVAL;
288 : : }
289 : :
290 : 0 : ret = iavf_node_param_check(vf, node_id, priority, weight,
291 : : params, error);
292 [ # # ]: 0 : if (ret)
293 : : return ret;
294 : :
295 : : /* check if the node is already existed */
296 [ # # ]: 0 : if (iavf_tm_node_search(dev, node_id, &node_type)) {
297 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
298 : 0 : error->message = "node id already used";
299 : 0 : return -EINVAL;
300 : : }
301 : :
302 : : /* check the shaper profile id */
303 [ # # ]: 0 : if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
304 : : shaper_profile = iavf_shaper_profile_search(dev,
305 : : params->shaper_profile_id);
306 [ # # ]: 0 : if (!shaper_profile) {
307 : 0 : error->type =
308 : : RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID;
309 : 0 : error->message = "shaper profile not exist";
310 : 0 : return -EINVAL;
311 : : }
312 : : }
313 : :
314 : : /* root node if not have a parent */
315 [ # # ]: 0 : if (parent_node_id == RTE_TM_NODE_ID_NULL) {
316 : : /* check level */
317 [ # # ]: 0 : if (level_id != IAVF_TM_NODE_TYPE_PORT) {
318 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
319 : 0 : error->message = "Wrong level";
320 : 0 : return -EINVAL;
321 : : }
322 : :
323 : : /* obviously no more than one root */
324 [ # # ]: 0 : if (vf->tm_conf.root) {
325 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
326 : 0 : error->message = "already have a root";
327 : 0 : return -EINVAL;
328 : : }
329 : :
330 : : /* add the root node */
331 : 0 : tm_node = rte_zmalloc("iavf_tm_node",
332 : : sizeof(struct iavf_tm_node),
333 : : 0);
334 [ # # ]: 0 : if (!tm_node)
335 : : return -ENOMEM;
336 : 0 : tm_node->id = node_id;
337 : 0 : tm_node->parent = NULL;
338 : 0 : tm_node->reference_count = 0;
339 : 0 : memcpy(&tm_node->params, params,
340 : : sizeof(struct rte_tm_node_params));
341 : 0 : vf->tm_conf.root = tm_node;
342 : 0 : return 0;
343 : : }
344 : :
345 : : /* TC or queue node */
346 : : /* check the parent node */
347 : 0 : parent_node = iavf_tm_node_search(dev, parent_node_id,
348 : : &parent_node_type);
349 [ # # ]: 0 : if (!parent_node) {
350 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
351 : 0 : error->message = "parent not exist";
352 : 0 : return -EINVAL;
353 : : }
354 [ # # ]: 0 : if (parent_node_type != IAVF_TM_NODE_TYPE_PORT &&
355 : : parent_node_type != IAVF_TM_NODE_TYPE_TC) {
356 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID;
357 : 0 : error->message = "parent is not root or TC";
358 : 0 : return -EINVAL;
359 : : }
360 : : /* check level */
361 [ # # ]: 0 : if (level_id != RTE_TM_NODE_LEVEL_ID_ANY &&
362 [ # # ]: 0 : level_id != (uint32_t)parent_node_type + 1) {
363 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
364 : 0 : error->message = "Wrong level";
365 : 0 : return -EINVAL;
366 : : }
367 : :
368 : : /* check the node number */
369 [ # # ]: 0 : if (parent_node_type == IAVF_TM_NODE_TYPE_PORT) {
370 : : /* check the TC number */
371 [ # # ]: 0 : if (vf->tm_conf.nb_tc_node >= tc_nb) {
372 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
373 : 0 : error->message = "too many TCs";
374 : 0 : return -EINVAL;
375 : : }
376 : : } else {
377 : : /* check the queue number */
378 [ # # ]: 0 : if (parent_node->reference_count >= vf->num_queue_pairs) {
379 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
380 : 0 : error->message = "too many queues";
381 : 0 : return -EINVAL;
382 : : }
383 [ # # ]: 0 : if (node_id >= vf->num_queue_pairs) {
384 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
385 : 0 : error->message = "too large queue id";
386 : 0 : return -EINVAL;
387 : : }
388 : : }
389 : :
390 : : /* add the TC or queue node */
391 : 0 : tm_node = rte_zmalloc("iavf_tm_node",
392 : : sizeof(struct iavf_tm_node),
393 : : 0);
394 [ # # ]: 0 : if (!tm_node)
395 : : return -ENOMEM;
396 : 0 : tm_node->id = node_id;
397 : 0 : tm_node->reference_count = 0;
398 : 0 : tm_node->parent = parent_node;
399 : 0 : tm_node->shaper_profile = shaper_profile;
400 [ # # ]: 0 : memcpy(&tm_node->params, params,
401 : : sizeof(struct rte_tm_node_params));
402 [ # # ]: 0 : if (parent_node_type == IAVF_TM_NODE_TYPE_PORT) {
403 : 0 : TAILQ_INSERT_TAIL(&vf->tm_conf.tc_list,
404 : : tm_node, node);
405 : 0 : tm_node->tc = vf->tm_conf.nb_tc_node;
406 : 0 : vf->tm_conf.nb_tc_node++;
407 : : } else {
408 : 0 : TAILQ_INSERT_TAIL(&vf->tm_conf.queue_list,
409 : : tm_node, node);
410 : 0 : tm_node->tc = parent_node->tc;
411 : 0 : vf->tm_conf.nb_queue_node++;
412 : : }
413 : 0 : tm_node->parent->reference_count++;
414 : :
415 : : /* increase the reference counter of the shaper profile */
416 [ # # ]: 0 : if (shaper_profile)
417 : 0 : shaper_profile->reference_count++;
418 : :
419 : : return 0;
420 : : }
421 : :
422 : : static int
423 : 0 : iavf_tm_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
424 : : struct rte_tm_error *error)
425 : : {
426 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
427 : 0 : enum iavf_tm_node_type node_type = IAVF_TM_NODE_TYPE_MAX;
428 : : struct iavf_tm_node *tm_node;
429 : :
430 [ # # ]: 0 : if (!error)
431 : : return -EINVAL;
432 : :
433 : : /* if already committed */
434 [ # # ]: 0 : if (vf->tm_conf.committed) {
435 : 0 : error->type = RTE_TM_ERROR_TYPE_UNSPECIFIED;
436 : 0 : error->message = "already committed";
437 : 0 : return -EINVAL;
438 : : }
439 : :
440 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
441 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
442 : 0 : error->message = "invalid node id";
443 : 0 : return -EINVAL;
444 : : }
445 : :
446 : : /* check if the node id exists */
447 : 0 : tm_node = iavf_tm_node_search(dev, node_id, &node_type);
448 [ # # ]: 0 : if (!tm_node) {
449 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
450 : 0 : error->message = "no such node";
451 : 0 : return -EINVAL;
452 : : }
453 : :
454 : : /* the node should have no child */
455 [ # # ]: 0 : if (tm_node->reference_count) {
456 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
457 : 0 : error->message =
458 : : "cannot delete a node which has children";
459 : 0 : return -EINVAL;
460 : : }
461 : :
462 : : /* root node */
463 [ # # ]: 0 : if (node_type == IAVF_TM_NODE_TYPE_PORT) {
464 : 0 : rte_free(tm_node);
465 : 0 : vf->tm_conf.root = NULL;
466 : 0 : return 0;
467 : : }
468 : :
469 : : /* TC or queue node */
470 : 0 : tm_node->parent->reference_count--;
471 [ # # ]: 0 : if (node_type == IAVF_TM_NODE_TYPE_TC) {
472 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.tc_list, tm_node, node);
473 : 0 : vf->tm_conf.nb_tc_node--;
474 : : } else {
475 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.queue_list, tm_node, node);
476 : 0 : vf->tm_conf.nb_queue_node--;
477 : : }
478 : 0 : rte_free(tm_node);
479 : :
480 : 0 : return 0;
481 : : }
482 : :
483 : : static int
484 : : iavf_shaper_profile_param_check(const struct rte_tm_shaper_params *profile,
485 : : struct rte_tm_error *error)
486 : : {
487 : : /* min bucket size not supported */
488 [ # # ]: 0 : if (profile->committed.size) {
489 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE;
490 : 0 : error->message = "committed bucket size not supported";
491 : : return -EINVAL;
492 : : }
493 : : /* max bucket size not supported */
494 [ # # ]: 0 : if (profile->peak.size) {
495 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE;
496 : 0 : error->message = "peak bucket size not supported";
497 : : return -EINVAL;
498 : : }
499 : : /* length adjustment not supported */
500 [ # # ]: 0 : if (profile->pkt_length_adjust) {
501 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN;
502 : 0 : error->message = "packet length adjustment not supported";
503 : : return -EINVAL;
504 : : }
505 : :
506 : : return 0;
507 : : }
508 : :
509 : : static int
510 : 0 : iavf_shaper_profile_add(struct rte_eth_dev *dev,
511 : : uint32_t shaper_profile_id,
512 : : const struct rte_tm_shaper_params *profile,
513 : : struct rte_tm_error *error)
514 : : {
515 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
516 : : struct iavf_tm_shaper_profile *shaper_profile;
517 : : int ret;
518 : :
519 [ # # ]: 0 : if (!profile || !error)
520 : : return -EINVAL;
521 : :
522 : : ret = iavf_shaper_profile_param_check(profile, error);
523 : : if (ret)
524 : 0 : return ret;
525 : :
526 : : shaper_profile = iavf_shaper_profile_search(dev, shaper_profile_id);
527 : :
528 [ # # ]: 0 : if (shaper_profile) {
529 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
530 : 0 : error->message = "profile ID exist";
531 : 0 : return -EINVAL;
532 : : }
533 : :
534 : 0 : shaper_profile = rte_zmalloc("iavf_tm_shaper_profile",
535 : : sizeof(struct iavf_tm_shaper_profile),
536 : : 0);
537 [ # # ]: 0 : if (!shaper_profile)
538 : : return -ENOMEM;
539 : 0 : shaper_profile->shaper_profile_id = shaper_profile_id;
540 : 0 : memcpy(&shaper_profile->profile, profile,
541 : : sizeof(struct rte_tm_shaper_params));
542 : 0 : TAILQ_INSERT_TAIL(&vf->tm_conf.shaper_profile_list,
543 : : shaper_profile, node);
544 : :
545 : 0 : return 0;
546 : : }
547 : :
548 : : static int
549 : 0 : iavf_shaper_profile_del(struct rte_eth_dev *dev,
550 : : uint32_t shaper_profile_id,
551 : : struct rte_tm_error *error)
552 : : {
553 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
554 : : struct iavf_tm_shaper_profile *shaper_profile;
555 : :
556 [ # # ]: 0 : if (!error)
557 : : return -EINVAL;
558 : :
559 : : shaper_profile = iavf_shaper_profile_search(dev, shaper_profile_id);
560 : :
561 [ # # ]: 0 : if (!shaper_profile) {
562 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID;
563 : 0 : error->message = "profile ID not exist";
564 : 0 : return -EINVAL;
565 : : }
566 : :
567 : : /* don't delete a profile if it's used by one or several nodes */
568 [ # # ]: 0 : if (shaper_profile->reference_count) {
569 : 0 : error->type = RTE_TM_ERROR_TYPE_SHAPER_PROFILE;
570 : 0 : error->message = "profile in use";
571 : 0 : return -EINVAL;
572 : : }
573 : :
574 [ # # ]: 0 : TAILQ_REMOVE(&vf->tm_conf.shaper_profile_list, shaper_profile, node);
575 : 0 : rte_free(shaper_profile);
576 : :
577 : 0 : return 0;
578 : : }
579 : :
580 : : static int
581 : 0 : iavf_tm_capabilities_get(struct rte_eth_dev *dev,
582 : : struct rte_tm_capabilities *cap,
583 : : struct rte_tm_error *error)
584 : : {
585 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
586 : 0 : uint16_t tc_nb = vf->qos_cap->num_elem;
587 : :
588 [ # # ]: 0 : if (!cap || !error)
589 : : return -EINVAL;
590 : :
591 [ # # ]: 0 : if (tc_nb > vf->vf_res->num_queue_pairs)
592 : : return -EINVAL;
593 : :
594 : 0 : error->type = RTE_TM_ERROR_TYPE_NONE;
595 : :
596 : : /* set all the parameters to 0 first. */
597 : : memset(cap, 0, sizeof(struct rte_tm_capabilities));
598 : :
599 : : /**
600 : : * support port + TCs + queues
601 : : * here shows the max capability not the current configuration.
602 : : */
603 : 0 : cap->n_nodes_max = 1 + IAVF_MAX_TRAFFIC_CLASS
604 : 0 : + vf->num_queue_pairs;
605 : 0 : cap->n_levels_max = 3; /* port, TC, queue */
606 : 0 : cap->non_leaf_nodes_identical = 1;
607 : 0 : cap->leaf_nodes_identical = 1;
608 : 0 : cap->shaper_n_max = cap->n_nodes_max;
609 : 0 : cap->shaper_private_n_max = cap->n_nodes_max;
610 : : cap->shaper_private_dual_rate_n_max = 0;
611 : : cap->shaper_private_rate_min = 0;
612 : : /* Bytes per second */
613 : 0 : cap->shaper_private_rate_max =
614 : 0 : (uint64_t)vf->link_speed * 1000000 / IAVF_BITS_PER_BYTE;
615 : : cap->shaper_private_packet_mode_supported = 0;
616 : 0 : cap->shaper_private_byte_mode_supported = 1;
617 : : cap->shaper_shared_n_max = 0;
618 : : cap->shaper_shared_n_nodes_per_shaper_max = 0;
619 : : cap->shaper_shared_n_shapers_per_node_max = 0;
620 : : cap->shaper_shared_dual_rate_n_max = 0;
621 : : cap->shaper_shared_rate_min = 0;
622 : : cap->shaper_shared_rate_max = 0;
623 : : cap->shaper_shared_packet_mode_supported = 0;
624 : : cap->shaper_shared_byte_mode_supported = 0;
625 : 0 : cap->sched_n_children_max = vf->num_queue_pairs;
626 : 0 : cap->sched_sp_n_priorities_max = 1;
627 : : cap->sched_wfq_n_children_per_group_max = 0;
628 : : cap->sched_wfq_n_groups_max = 0;
629 : 0 : cap->sched_wfq_weight_max = 1;
630 : : cap->sched_wfq_packet_mode_supported = 0;
631 : : cap->sched_wfq_byte_mode_supported = 0;
632 : : cap->cman_head_drop_supported = 0;
633 : : cap->dynamic_update_mask = 0;
634 : 0 : cap->shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD;
635 : 0 : cap->shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
636 : : cap->cman_wred_context_n_max = 0;
637 : : cap->cman_wred_context_private_n_max = 0;
638 : : cap->cman_wred_context_shared_n_max = 0;
639 : : cap->cman_wred_context_shared_n_nodes_per_context_max = 0;
640 : : cap->cman_wred_context_shared_n_contexts_per_node_max = 0;
641 : : cap->stats_mask = 0;
642 : :
643 : 0 : return 0;
644 : : }
645 : :
646 : : static int
647 : 0 : iavf_level_capabilities_get(struct rte_eth_dev *dev,
648 : : uint32_t level_id,
649 : : struct rte_tm_level_capabilities *cap,
650 : : struct rte_tm_error *error)
651 : : {
652 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
653 : :
654 [ # # ]: 0 : if (!cap || !error)
655 : : return -EINVAL;
656 : :
657 [ # # ]: 0 : if (level_id >= IAVF_TM_NODE_TYPE_MAX) {
658 : 0 : error->type = RTE_TM_ERROR_TYPE_LEVEL_ID;
659 : 0 : error->message = "too deep level";
660 : 0 : return -EINVAL;
661 : : }
662 : :
663 : : /* root node */
664 [ # # ]: 0 : if (level_id == IAVF_TM_NODE_TYPE_PORT) {
665 : 0 : cap->n_nodes_max = 1;
666 : 0 : cap->n_nodes_nonleaf_max = 1;
667 : 0 : cap->n_nodes_leaf_max = 0;
668 [ # # ]: 0 : } else if (level_id == IAVF_TM_NODE_TYPE_TC) {
669 : : /* TC */
670 : 0 : cap->n_nodes_max = IAVF_MAX_TRAFFIC_CLASS;
671 : 0 : cap->n_nodes_nonleaf_max = IAVF_MAX_TRAFFIC_CLASS;
672 : 0 : cap->n_nodes_leaf_max = 0;
673 : : } else {
674 : : /* queue */
675 : 0 : cap->n_nodes_max = vf->num_queue_pairs;
676 : 0 : cap->n_nodes_nonleaf_max = 0;
677 : 0 : cap->n_nodes_leaf_max = vf->num_queue_pairs;
678 : : }
679 : :
680 : 0 : cap->non_leaf_nodes_identical = true;
681 : 0 : cap->leaf_nodes_identical = true;
682 : :
683 [ # # ]: 0 : if (level_id != IAVF_TM_NODE_TYPE_QUEUE) {
684 : 0 : cap->nonleaf.shaper_private_supported = true;
685 : 0 : cap->nonleaf.shaper_private_dual_rate_supported = false;
686 : 0 : cap->nonleaf.shaper_private_rate_min = 0;
687 : : /* Bytes per second */
688 : 0 : cap->nonleaf.shaper_private_rate_max =
689 : 0 : (uint64_t)vf->link_speed * 1000000 / IAVF_BITS_PER_BYTE;
690 : 0 : cap->nonleaf.shaper_private_packet_mode_supported = 0;
691 : 0 : cap->nonleaf.shaper_private_byte_mode_supported = 1;
692 : 0 : cap->nonleaf.shaper_shared_n_max = 0;
693 : 0 : cap->nonleaf.shaper_shared_packet_mode_supported = 0;
694 : 0 : cap->nonleaf.shaper_shared_byte_mode_supported = 0;
695 [ # # ]: 0 : if (level_id == IAVF_TM_NODE_TYPE_PORT)
696 : 0 : cap->nonleaf.sched_n_children_max =
697 : : IAVF_MAX_TRAFFIC_CLASS;
698 : : else
699 : 0 : cap->nonleaf.sched_n_children_max =
700 : 0 : vf->num_queue_pairs;
701 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 1;
702 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 0;
703 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
704 : 0 : cap->nonleaf.sched_wfq_weight_max = 1;
705 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported = 0;
706 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported = 0;
707 : 0 : cap->nonleaf.stats_mask = 0;
708 : :
709 : 0 : return 0;
710 : : }
711 : :
712 : : /* queue node */
713 : 0 : cap->leaf.shaper_private_supported = false;
714 : 0 : cap->leaf.shaper_private_dual_rate_supported = false;
715 : 0 : cap->leaf.shaper_private_rate_min = 0;
716 : : /* Bytes per second */
717 : 0 : cap->leaf.shaper_private_rate_max =
718 : 0 : (uint64_t)vf->link_speed * 1000000 / IAVF_BITS_PER_BYTE;
719 : 0 : cap->leaf.shaper_private_packet_mode_supported = 0;
720 : 0 : cap->leaf.shaper_private_byte_mode_supported = 1;
721 : 0 : cap->leaf.shaper_shared_n_max = 0;
722 : 0 : cap->leaf.shaper_shared_packet_mode_supported = 0;
723 : 0 : cap->leaf.shaper_shared_byte_mode_supported = 0;
724 : 0 : cap->leaf.cman_head_drop_supported = false;
725 : 0 : cap->leaf.cman_wred_context_private_supported = true;
726 : 0 : cap->leaf.cman_wred_context_shared_n_max = 0;
727 : 0 : cap->leaf.stats_mask = 0;
728 : :
729 : 0 : return 0;
730 : : }
731 : :
732 : : static int
733 : 0 : iavf_node_capabilities_get(struct rte_eth_dev *dev,
734 : : uint32_t node_id,
735 : : struct rte_tm_node_capabilities *cap,
736 : : struct rte_tm_error *error)
737 : : {
738 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
739 : : enum iavf_tm_node_type node_type;
740 : : struct virtchnl_qos_cap_elem tc_cap;
741 : : struct iavf_tm_node *tm_node;
742 : :
743 [ # # ]: 0 : if (!cap || !error)
744 : : return -EINVAL;
745 : :
746 [ # # ]: 0 : if (node_id == RTE_TM_NODE_ID_NULL) {
747 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
748 : 0 : error->message = "invalid node id";
749 : 0 : return -EINVAL;
750 : : }
751 : :
752 : : /* check if the node id exists */
753 : 0 : tm_node = iavf_tm_node_search(dev, node_id, &node_type);
754 [ # # ]: 0 : if (!tm_node) {
755 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_ID;
756 : 0 : error->message = "no such node";
757 : 0 : return -EINVAL;
758 : : }
759 : :
760 [ # # ]: 0 : if (node_type != IAVF_TM_NODE_TYPE_TC) {
761 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
762 : 0 : error->message = "not support capability get";
763 : 0 : return -EINVAL;
764 : : }
765 : :
766 : 0 : tc_cap = vf->qos_cap->cap[tm_node->tc];
767 [ # # ]: 0 : if (tc_cap.tc_num != tm_node->tc) {
768 : 0 : error->type = RTE_TM_ERROR_TYPE_NODE_PARAMS;
769 : 0 : error->message = "tc not match";
770 : 0 : return -EINVAL;
771 : : }
772 : :
773 : 0 : cap->shaper_private_supported = true;
774 : 0 : cap->shaper_private_dual_rate_supported = false;
775 : : /* Bytes per second */
776 : 0 : cap->shaper_private_rate_min =
777 : 0 : (uint64_t)tc_cap.shaper.committed * 1000 / IAVF_BITS_PER_BYTE;
778 : 0 : cap->shaper_private_rate_max =
779 : 0 : (uint64_t)tc_cap.shaper.peak * 1000 / IAVF_BITS_PER_BYTE;
780 : 0 : cap->shaper_shared_n_max = 0;
781 : 0 : cap->nonleaf.sched_n_children_max = vf->num_queue_pairs;
782 : 0 : cap->nonleaf.sched_sp_n_priorities_max = 1;
783 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max = 1;
784 : 0 : cap->nonleaf.sched_wfq_n_groups_max = 0;
785 : 0 : cap->nonleaf.sched_wfq_weight_max = tc_cap.weight;
786 : 0 : cap->stats_mask = 0;
787 : :
788 : 0 : return 0;
789 : : }
790 : :
791 : 0 : static int iavf_hierarchy_commit(struct rte_eth_dev *dev,
792 : : int clear_on_fail,
793 : : __rte_unused struct rte_tm_error *error)
794 : : {
795 : 0 : struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
796 : : struct iavf_adapter *adapter =
797 : : IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
798 : : struct virtchnl_queue_tc_mapping *q_tc_mapping;
799 : : struct virtchnl_queues_bw_cfg *q_bw;
800 : : struct iavf_tm_node_list *queue_list = &vf->tm_conf.queue_list;
801 : : struct iavf_tm_node *tm_node;
802 : : struct iavf_qtc_map *qtc_map;
803 : : uint16_t size, size_q;
804 : : int index = 0, node_committed = 0;
805 : : int i, ret_val = IAVF_SUCCESS;
806 : :
807 : : /* check if port is stopped */
808 [ # # ]: 0 : if (adapter->stopped != 1) {
809 : 0 : PMD_DRV_LOG(ERR, "Please stop port first");
810 : : ret_val = IAVF_ERR_NOT_READY;
811 : 0 : goto err;
812 : : }
813 : :
814 [ # # ]: 0 : if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS)) {
815 : 0 : PMD_DRV_LOG(ERR, "VF queue tc mapping is not supported");
816 : : ret_val = IAVF_NOT_SUPPORTED;
817 : 0 : goto fail_clear;
818 : : }
819 : :
820 : : /* check if all TC nodes are set with VF vsi */
821 [ # # ]: 0 : if (vf->tm_conf.nb_tc_node != vf->qos_cap->num_elem) {
822 : 0 : PMD_DRV_LOG(ERR, "Does not set VF vsi nodes to all TCs");
823 : : ret_val = IAVF_ERR_PARAM;
824 : 0 : goto fail_clear;
825 : : }
826 : :
827 : 0 : size = sizeof(*q_tc_mapping) + sizeof(q_tc_mapping->tc[0]) *
828 : : (vf->qos_cap->num_elem - 1);
829 : 0 : q_tc_mapping = rte_zmalloc("q_tc", size, 0);
830 [ # # ]: 0 : if (!q_tc_mapping) {
831 : : ret_val = IAVF_ERR_NO_MEMORY;
832 : 0 : goto fail_clear;
833 : : }
834 : :
835 : 0 : size_q = sizeof(*q_bw) + sizeof(q_bw->cfg[0]) *
836 : 0 : (vf->num_queue_pairs - 1);
837 : 0 : q_bw = rte_zmalloc("q_bw", size_q, 0);
838 [ # # ]: 0 : if (!q_bw) {
839 : : ret_val = IAVF_ERR_NO_MEMORY;
840 : 0 : goto fail_clear;
841 : : }
842 : :
843 : 0 : q_tc_mapping->vsi_id = vf->vsi.vsi_id;
844 : 0 : q_tc_mapping->num_tc = vf->qos_cap->num_elem;
845 : 0 : q_tc_mapping->num_queue_pairs = vf->num_queue_pairs;
846 : :
847 : 0 : q_bw->vsi_id = vf->vsi.vsi_id;
848 : 0 : q_bw->num_queues = vf->num_queue_pairs;
849 : :
850 [ # # ]: 0 : TAILQ_FOREACH(tm_node, queue_list, node) {
851 [ # # ]: 0 : if (tm_node->tc >= q_tc_mapping->num_tc) {
852 : 0 : PMD_DRV_LOG(ERR, "TC%d is not enabled", tm_node->tc);
853 : : ret_val = IAVF_ERR_PARAM;
854 : 0 : goto fail_clear;
855 : : }
856 : 0 : q_tc_mapping->tc[tm_node->tc].req.queue_count++;
857 : :
858 [ # # ]: 0 : if (tm_node->shaper_profile) {
859 : 0 : q_bw->cfg[node_committed].queue_id = node_committed;
860 : 0 : q_bw->cfg[node_committed].shaper.peak =
861 : 0 : tm_node->shaper_profile->profile.peak.rate /
862 : : 1000 * IAVF_BITS_PER_BYTE;
863 : 0 : q_bw->cfg[node_committed].shaper.committed =
864 : 0 : tm_node->shaper_profile->profile.committed.rate /
865 : : 1000 * IAVF_BITS_PER_BYTE;
866 : 0 : q_bw->cfg[node_committed].tc = tm_node->tc;
867 : : }
868 : :
869 : 0 : node_committed++;
870 : : }
871 : :
872 : : /* All queues allocated to this VF should be mapped */
873 [ # # ]: 0 : if (node_committed < vf->num_queue_pairs) {
874 : 0 : PMD_DRV_LOG(ERR, "queue node is less than allocated queue pairs");
875 : : ret_val = IAVF_ERR_PARAM;
876 : 0 : goto fail_clear;
877 : : }
878 : :
879 : 0 : ret_val = iavf_set_q_bw(dev, q_bw, size_q);
880 [ # # ]: 0 : if (ret_val)
881 : 0 : goto fail_clear;
882 : :
883 : : /* store the queue TC mapping info */
884 : 0 : qtc_map = rte_zmalloc("qtc_map",
885 : 0 : sizeof(struct iavf_qtc_map) * q_tc_mapping->num_tc, 0);
886 [ # # ]: 0 : if (!qtc_map)
887 : : return IAVF_ERR_NO_MEMORY;
888 : :
889 [ # # ]: 0 : for (i = 0; i < q_tc_mapping->num_tc; i++) {
890 : 0 : q_tc_mapping->tc[i].req.start_queue_id = index;
891 : 0 : index += q_tc_mapping->tc[i].req.queue_count;
892 : 0 : qtc_map[i].tc = i;
893 : 0 : qtc_map[i].start_queue_id =
894 : : q_tc_mapping->tc[i].req.start_queue_id;
895 : 0 : qtc_map[i].queue_count = q_tc_mapping->tc[i].req.queue_count;
896 : : }
897 : :
898 : 0 : ret_val = iavf_set_q_tc_map(dev, q_tc_mapping, size);
899 [ # # ]: 0 : if (ret_val)
900 : 0 : goto fail_clear;
901 : :
902 : 0 : vf->qtc_map = qtc_map;
903 : 0 : vf->tm_conf.committed = true;
904 : 0 : return ret_val;
905 : :
906 : 0 : fail_clear:
907 : : /* clear all the traffic manager configuration */
908 [ # # ]: 0 : if (clear_on_fail) {
909 : 0 : iavf_tm_conf_uninit(dev);
910 : 0 : iavf_tm_conf_init(dev);
911 : : }
912 : 0 : err:
913 : : return ret_val;
914 : : }
|