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