1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright (c) 2021, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the Intel Corporation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*$FreeBSD$*/
32
33 #include "ice_sched.h"
34
35 /**
36 * ice_sched_add_root_node - Insert the Tx scheduler root node in SW DB
37 * @pi: port information structure
38 * @info: Scheduler element information from firmware
39 *
40 * This function inserts the root node of the scheduling tree topology
41 * to the SW DB.
42 */
43 static enum ice_status
44 ice_sched_add_root_node(struct ice_port_info *pi,
45 struct ice_aqc_txsched_elem_data *info)
46 {
47 struct ice_sched_node *root;
48 struct ice_hw *hw;
49
50 if (!pi)
51 return ICE_ERR_PARAM;
52
53 hw = pi->hw;
54
55 root = (struct ice_sched_node *)ice_malloc(hw, sizeof(*root));
56 if (!root)
57 return ICE_ERR_NO_MEMORY;
58
59 /* coverity[suspicious_sizeof] */
60 root->children = (struct ice_sched_node **)
61 ice_calloc(hw, hw->max_children[0], sizeof(*root));
62 if (!root->children) {
63 ice_free(hw, root);
64 return ICE_ERR_NO_MEMORY;
65 }
66
67 ice_memcpy(&root->info, info, sizeof(*info), ICE_DMA_TO_NONDMA);
68 pi->root = root;
69 return ICE_SUCCESS;
70 }
71
72 /**
73 * ice_sched_find_node_by_teid - Find the Tx scheduler node in SW DB
74 * @start_node: pointer to the starting ice_sched_node struct in a sub-tree
75 * @teid: node TEID to search
76 *
77 * This function searches for a node matching the TEID in the scheduling tree
78 * from the SW DB. The search is recursive and is restricted by the number of
79 * layers it has searched through; stopping at the max supported layer.
80 *
81 * This function needs to be called when holding the port_info->sched_lock
82 */
83 struct ice_sched_node *
84 ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid)
85 {
86 u16 i;
87
88 /* The TEID is same as that of the start_node */
89 if (ICE_TXSCHED_GET_NODE_TEID(start_node) == teid)
90 return start_node;
91
92 /* The node has no children or is at the max layer */
93 if (!start_node->num_children ||
94 start_node->tx_sched_layer >= ICE_AQC_TOPO_MAX_LEVEL_NUM ||
95 start_node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF)
96 return NULL;
97
98 /* Check if TEID matches to any of the children nodes */
99 for (i = 0; i < start_node->num_children; i++)
100 if (ICE_TXSCHED_GET_NODE_TEID(start_node->children[i]) == teid)
101 return start_node->children[i];
102
103 /* Search within each child's sub-tree */
104 for (i = 0; i < start_node->num_children; i++) {
105 struct ice_sched_node *tmp;
106
107 tmp = ice_sched_find_node_by_teid(start_node->children[i],
108 teid);
109 if (tmp)
110 return tmp;
111 }
112
113 return NULL;
114 }
115
116 /**
117 * ice_aqc_send_sched_elem_cmd - send scheduling elements cmd
118 * @hw: pointer to the HW struct
119 * @cmd_opc: cmd opcode
120 * @elems_req: number of elements to request
121 * @buf: pointer to buffer
122 * @buf_size: buffer size in bytes
123 * @elems_resp: returns total number of elements response
124 * @cd: pointer to command details structure or NULL
125 *
126 * This function sends a scheduling elements cmd (cmd_opc)
127 */
128 static enum ice_status
129 ice_aqc_send_sched_elem_cmd(struct ice_hw *hw, enum ice_adminq_opc cmd_opc,
130 u16 elems_req, void *buf, u16 buf_size,
131 u16 *elems_resp, struct ice_sq_cd *cd)
132 {
133 struct ice_aqc_sched_elem_cmd *cmd;
134 struct ice_aq_desc desc;
135 enum ice_status status;
136
137 cmd = &desc.params.sched_elem_cmd;
138 ice_fill_dflt_direct_cmd_desc(&desc, cmd_opc);
139 cmd->num_elem_req = CPU_TO_LE16(elems_req);
140 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
141 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
142 if (!status && elems_resp)
143 *elems_resp = LE16_TO_CPU(cmd->num_elem_resp);
144
145 return status;
146 }
147
148 /**
149 * ice_aq_query_sched_elems - query scheduler elements
150 * @hw: pointer to the HW struct
151 * @elems_req: number of elements to query
152 * @buf: pointer to buffer
153 * @buf_size: buffer size in bytes
154 * @elems_ret: returns total number of elements returned
155 * @cd: pointer to command details structure or NULL
156 *
157 * Query scheduling elements (0x0404)
158 */
159 enum ice_status
160 ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,
161 struct ice_aqc_txsched_elem_data *buf, u16 buf_size,
162 u16 *elems_ret, struct ice_sq_cd *cd)
163 {
164 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_get_sched_elems,
165 elems_req, (void *)buf, buf_size,
166 elems_ret, cd);
167 }
168
169 /**
170 * ice_sched_add_node - Insert the Tx scheduler node in SW DB
171 * @pi: port information structure
172 * @layer: Scheduler layer of the node
173 * @info: Scheduler element information from firmware
174 *
175 * This function inserts a scheduler node to the SW DB.
176 */
177 enum ice_status
178 ice_sched_add_node(struct ice_port_info *pi, u8 layer,
179 struct ice_aqc_txsched_elem_data *info)
180 {
181 struct ice_aqc_txsched_elem_data elem;
182 struct ice_sched_node *parent;
183 struct ice_sched_node *node;
184 enum ice_status status;
185 struct ice_hw *hw;
186
187 if (!pi)
188 return ICE_ERR_PARAM;
189
190 hw = pi->hw;
191
192 /* A valid parent node should be there */
193 parent = ice_sched_find_node_by_teid(pi->root,
194 LE32_TO_CPU(info->parent_teid));
195 if (!parent) {
196 ice_debug(hw, ICE_DBG_SCHED, "Parent Node not found for parent_teid=0x%x\n",
197 LE32_TO_CPU(info->parent_teid));
198 return ICE_ERR_PARAM;
199 }
200
201 /* query the current node information from FW before adding it
202 * to the SW DB
203 */
204 status = ice_sched_query_elem(hw, LE32_TO_CPU(info->node_teid), &elem);
205 if (status)
206 return status;
207 node = (struct ice_sched_node *)ice_malloc(hw, sizeof(*node));
208 if (!node)
209 return ICE_ERR_NO_MEMORY;
210 if (hw->max_children[layer]) {
211 /* coverity[suspicious_sizeof] */
212 node->children = (struct ice_sched_node **)
213 ice_calloc(hw, hw->max_children[layer], sizeof(*node));
214 if (!node->children) {
215 ice_free(hw, node);
216 return ICE_ERR_NO_MEMORY;
217 }
218 }
219
220 node->in_use = true;
221 node->parent = parent;
222 node->tx_sched_layer = layer;
223 parent->children[parent->num_children++] = node;
224 node->info = elem;
225 return ICE_SUCCESS;
226 }
227
228 /**
229 * ice_aq_delete_sched_elems - delete scheduler elements
230 * @hw: pointer to the HW struct
231 * @grps_req: number of groups to delete
232 * @buf: pointer to buffer
233 * @buf_size: buffer size in bytes
234 * @grps_del: returns total number of elements deleted
235 * @cd: pointer to command details structure or NULL
236 *
237 * Delete scheduling elements (0x040F)
238 */
239 static enum ice_status
240 ice_aq_delete_sched_elems(struct ice_hw *hw, u16 grps_req,
241 struct ice_aqc_delete_elem *buf, u16 buf_size,
242 u16 *grps_del, struct ice_sq_cd *cd)
243 {
244 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_delete_sched_elems,
245 grps_req, (void *)buf, buf_size,
246 grps_del, cd);
247 }
248
249 /**
250 * ice_sched_remove_elems - remove nodes from HW
251 * @hw: pointer to the HW struct
252 * @parent: pointer to the parent node
253 * @num_nodes: number of nodes
254 * @node_teids: array of node teids to be deleted
255 *
256 * This function remove nodes from HW
257 */
258 static enum ice_status
259 ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
260 u16 num_nodes, u32 *node_teids)
261 {
262 struct ice_aqc_delete_elem *buf;
263 u16 i, num_groups_removed = 0;
264 enum ice_status status;
265 u16 buf_size;
266
267 buf_size = ice_struct_size(buf, teid, num_nodes);
268 buf = (struct ice_aqc_delete_elem *)ice_malloc(hw, buf_size);
269 if (!buf)
270 return ICE_ERR_NO_MEMORY;
271
272 buf->hdr.parent_teid = parent->info.node_teid;
273 buf->hdr.num_elems = CPU_TO_LE16(num_nodes);
274 for (i = 0; i < num_nodes; i++)
275 buf->teid[i] = CPU_TO_LE32(node_teids[i]);
276
277 status = ice_aq_delete_sched_elems(hw, 1, buf, buf_size,
278 &num_groups_removed, NULL);
279 if (status != ICE_SUCCESS || num_groups_removed != 1)
280 ice_debug(hw, ICE_DBG_SCHED, "remove node failed FW error %d\n",
281 hw->adminq.sq_last_status);
282
283 ice_free(hw, buf);
284 return status;
285 }
286
287 /**
288 * ice_sched_get_first_node - get the first node of the given layer
289 * @pi: port information structure
290 * @parent: pointer the base node of the subtree
291 * @layer: layer number
292 *
293 * This function retrieves the first node of the given layer from the subtree
294 */
295 static struct ice_sched_node *
296 ice_sched_get_first_node(struct ice_port_info *pi,
297 struct ice_sched_node *parent, u8 layer)
298 {
299 return pi->sib_head[parent->tc_num][layer];
300 }
301
302 /**
303 * ice_sched_get_tc_node - get pointer to TC node
304 * @pi: port information structure
305 * @tc: TC number
306 *
307 * This function returns the TC node pointer
308 */
309 struct ice_sched_node *ice_sched_get_tc_node(struct ice_port_info *pi, u8 tc)
310 {
311 u8 i;
312
313 if (!pi || !pi->root)
314 return NULL;
315 for (i = 0; i < pi->root->num_children; i++)
316 if (pi->root->children[i]->tc_num == tc)
317 return pi->root->children[i];
318 return NULL;
319 }
320
321 /**
322 * ice_free_sched_node - Free a Tx scheduler node from SW DB
323 * @pi: port information structure
324 * @node: pointer to the ice_sched_node struct
325 *
326 * This function frees up a node from SW DB as well as from HW
327 *
328 * This function needs to be called with the port_info->sched_lock held
329 */
330 void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
331 {
332 struct ice_sched_node *parent;
333 struct ice_hw *hw = pi->hw;
334 u8 i, j;
335
336 /* Free the children before freeing up the parent node
337 * The parent array is updated below and that shifts the nodes
338 * in the array. So always pick the first child if num children > 0
339 */
340 while (node->num_children)
341 ice_free_sched_node(pi, node->children[0]);
342
343 /* Leaf, TC and root nodes can't be deleted by SW */
344 if (node->tx_sched_layer >= hw->sw_entry_point_layer &&
345 node->info.data.elem_type != ICE_AQC_ELEM_TYPE_TC &&
346 node->info.data.elem_type != ICE_AQC_ELEM_TYPE_ROOT_PORT &&
347 node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF) {
348 u32 teid = LE32_TO_CPU(node->info.node_teid);
349
350 ice_sched_remove_elems(hw, node->parent, 1, &teid);
351 }
352 parent = node->parent;
353 /* root has no parent */
354 if (parent) {
355 struct ice_sched_node *p;
356
357 /* update the parent */
358 for (i = 0; i < parent->num_children; i++)
359 if (parent->children[i] == node) {
360 for (j = i + 1; j < parent->num_children; j++)
361 parent->children[j - 1] =
362 parent->children[j];
363 parent->num_children--;
364 break;
365 }
366
367 p = ice_sched_get_first_node(pi, node, node->tx_sched_layer);
368 while (p) {
369 if (p->sibling == node) {
370 p->sibling = node->sibling;
371 break;
372 }
373 p = p->sibling;
374 }
375
376 /* update the sibling head if head is getting removed */
377 if (pi->sib_head[node->tc_num][node->tx_sched_layer] == node)
378 pi->sib_head[node->tc_num][node->tx_sched_layer] =
379 node->sibling;
380 }
381
382 /* leaf nodes have no children */
383 if (node->children)
384 ice_free(hw, node->children);
385 ice_free(hw, node);
386 }
387
388 /**
389 * ice_aq_get_dflt_topo - gets default scheduler topology
390 * @hw: pointer to the HW struct
391 * @lport: logical port number
392 * @buf: pointer to buffer
393 * @buf_size: buffer size in bytes
394 * @num_branches: returns total number of queue to port branches
395 * @cd: pointer to command details structure or NULL
396 *
397 * Get default scheduler topology (0x400)
398 */
399 static enum ice_status
400 ice_aq_get_dflt_topo(struct ice_hw *hw, u8 lport,
401 struct ice_aqc_get_topo_elem *buf, u16 buf_size,
402 u8 *num_branches, struct ice_sq_cd *cd)
403 {
404 struct ice_aqc_get_topo *cmd;
405 struct ice_aq_desc desc;
406 enum ice_status status;
407
408 cmd = &desc.params.get_topo;
409 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_dflt_topo);
410 cmd->port_num = lport;
411 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
412 if (!status && num_branches)
413 *num_branches = cmd->num_branches;
414
415 return status;
416 }
417
418 /**
419 * ice_aq_add_sched_elems - adds scheduling element
420 * @hw: pointer to the HW struct
421 * @grps_req: the number of groups that are requested to be added
422 * @buf: pointer to buffer
423 * @buf_size: buffer size in bytes
424 * @grps_added: returns total number of groups added
425 * @cd: pointer to command details structure or NULL
426 *
427 * Add scheduling elements (0x0401)
428 */
429 static enum ice_status
430 ice_aq_add_sched_elems(struct ice_hw *hw, u16 grps_req,
431 struct ice_aqc_add_elem *buf, u16 buf_size,
432 u16 *grps_added, struct ice_sq_cd *cd)
433 {
434 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_add_sched_elems,
435 grps_req, (void *)buf, buf_size,
436 grps_added, cd);
437 }
438
439 /**
440 * ice_aq_cfg_sched_elems - configures scheduler elements
441 * @hw: pointer to the HW struct
442 * @elems_req: number of elements to configure
443 * @buf: pointer to buffer
444 * @buf_size: buffer size in bytes
445 * @elems_cfgd: returns total number of elements configured
446 * @cd: pointer to command details structure or NULL
447 *
448 * Configure scheduling elements (0x0403)
449 */
450 static enum ice_status
451 ice_aq_cfg_sched_elems(struct ice_hw *hw, u16 elems_req,
452 struct ice_aqc_txsched_elem_data *buf, u16 buf_size,
453 u16 *elems_cfgd, struct ice_sq_cd *cd)
454 {
455 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_cfg_sched_elems,
456 elems_req, (void *)buf, buf_size,
457 elems_cfgd, cd);
458 }
459
460 /**
461 * ice_aq_move_sched_elems - move scheduler elements
462 * @hw: pointer to the HW struct
463 * @grps_req: number of groups to move
464 * @buf: pointer to buffer
465 * @buf_size: buffer size in bytes
466 * @grps_movd: returns total number of groups moved
467 * @cd: pointer to command details structure or NULL
468 *
469 * Move scheduling elements (0x0408)
470 */
471 static enum ice_status
472 ice_aq_move_sched_elems(struct ice_hw *hw, u16 grps_req,
473 struct ice_aqc_move_elem *buf, u16 buf_size,
474 u16 *grps_movd, struct ice_sq_cd *cd)
475 {
476 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_move_sched_elems,
477 grps_req, (void *)buf, buf_size,
478 grps_movd, cd);
479 }
480
481 /**
482 * ice_aq_suspend_sched_elems - suspend scheduler elements
483 * @hw: pointer to the HW struct
484 * @elems_req: number of elements to suspend
485 * @buf: pointer to buffer
486 * @buf_size: buffer size in bytes
487 * @elems_ret: returns total number of elements suspended
488 * @cd: pointer to command details structure or NULL
489 *
490 * Suspend scheduling elements (0x0409)
491 */
492 static enum ice_status
493 ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req, __le32 *buf,
494 u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
495 {
496 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_suspend_sched_elems,
497 elems_req, (void *)buf, buf_size,
498 elems_ret, cd);
499 }
500
501 /**
502 * ice_aq_resume_sched_elems - resume scheduler elements
503 * @hw: pointer to the HW struct
504 * @elems_req: number of elements to resume
505 * @buf: pointer to buffer
506 * @buf_size: buffer size in bytes
507 * @elems_ret: returns total number of elements resumed
508 * @cd: pointer to command details structure or NULL
509 *
510 * resume scheduling elements (0x040A)
511 */
512 static enum ice_status
513 ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req, __le32 *buf,
514 u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
515 {
516 return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_resume_sched_elems,
517 elems_req, (void *)buf, buf_size,
518 elems_ret, cd);
519 }
520
521 /**
522 * ice_aq_query_sched_res - query scheduler resource
523 * @hw: pointer to the HW struct
524 * @buf_size: buffer size in bytes
525 * @buf: pointer to buffer
526 * @cd: pointer to command details structure or NULL
527 *
528 * Query scheduler resource allocation (0x0412)
529 */
530 static enum ice_status
531 ice_aq_query_sched_res(struct ice_hw *hw, u16 buf_size,
532 struct ice_aqc_query_txsched_res_resp *buf,
533 struct ice_sq_cd *cd)
534 {
535 struct ice_aq_desc desc;
536
537 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_sched_res);
538 return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
539 }
540
541 /**
542 * ice_sched_suspend_resume_elems - suspend or resume HW nodes
543 * @hw: pointer to the HW struct
544 * @num_nodes: number of nodes
545 * @node_teids: array of node teids to be suspended or resumed
546 * @suspend: true means suspend / false means resume
547 *
548 * This function suspends or resumes HW nodes
549 */
550 static enum ice_status
551 ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids,
552 bool suspend)
553 {
554 u16 i, buf_size, num_elem_ret = 0;
555 enum ice_status status;
556 __le32 *buf;
557
558 buf_size = sizeof(*buf) * num_nodes;
559 buf = (__le32 *)ice_malloc(hw, buf_size);
560 if (!buf)
561 return ICE_ERR_NO_MEMORY;
562
563 for (i = 0; i < num_nodes; i++)
564 buf[i] = CPU_TO_LE32(node_teids[i]);
565
566 if (suspend)
567 status = ice_aq_suspend_sched_elems(hw, num_nodes, buf,
568 buf_size, &num_elem_ret,
569 NULL);
570 else
571 status = ice_aq_resume_sched_elems(hw, num_nodes, buf,
572 buf_size, &num_elem_ret,
573 NULL);
574 if (status != ICE_SUCCESS || num_elem_ret != num_nodes)
575 ice_debug(hw, ICE_DBG_SCHED, "suspend/resume failed\n");
576
577 ice_free(hw, buf);
578 return status;
579 }
580
581 /**
582 * ice_alloc_lan_q_ctx - allocate LAN queue contexts for the given VSI and TC
583 * @hw: pointer to the HW struct
584 * @vsi_handle: VSI handle
585 * @tc: TC number
586 * @new_numqs: number of queues
587 */
588 static enum ice_status
589 ice_alloc_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 new_numqs)
590 {
591 struct ice_vsi_ctx *vsi_ctx;
592 struct ice_q_ctx *q_ctx;
593
594 vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
595 if (!vsi_ctx)
596 return ICE_ERR_PARAM;
597 /* allocate LAN queue contexts */
598 if (!vsi_ctx->lan_q_ctx[tc]) {
599 vsi_ctx->lan_q_ctx[tc] = (struct ice_q_ctx *)
600 ice_calloc(hw, new_numqs, sizeof(*q_ctx));
601 if (!vsi_ctx->lan_q_ctx[tc])
602 return ICE_ERR_NO_MEMORY;
603 vsi_ctx->num_lan_q_entries[tc] = new_numqs;
604 return ICE_SUCCESS;
605 }
606 /* num queues are increased, update the queue contexts */
607 if (new_numqs > vsi_ctx->num_lan_q_entries[tc]) {
608 u16 prev_num = vsi_ctx->num_lan_q_entries[tc];
609
610 q_ctx = (struct ice_q_ctx *)
611 ice_calloc(hw, new_numqs, sizeof(*q_ctx));
612 if (!q_ctx)
613 return ICE_ERR_NO_MEMORY;
614 ice_memcpy(q_ctx, vsi_ctx->lan_q_ctx[tc],
615 prev_num * sizeof(*q_ctx), ICE_DMA_TO_NONDMA);
616 ice_free(hw, vsi_ctx->lan_q_ctx[tc]);
617 vsi_ctx->lan_q_ctx[tc] = q_ctx;
618 vsi_ctx->num_lan_q_entries[tc] = new_numqs;
619 }
620 return ICE_SUCCESS;
621 }
622
623 /**
624 * ice_alloc_rdma_q_ctx - allocate RDMA queue contexts for the given VSI and TC
625 * @hw: pointer to the HW struct
626 * @vsi_handle: VSI handle
627 * @tc: TC number
628 * @new_numqs: number of queues
629 */
630 static enum ice_status
631 ice_alloc_rdma_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 new_numqs)
632 {
633 struct ice_vsi_ctx *vsi_ctx;
634 struct ice_q_ctx *q_ctx;
635
636 vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
637 if (!vsi_ctx)
638 return ICE_ERR_PARAM;
639 /* allocate RDMA queue contexts */
640 if (!vsi_ctx->rdma_q_ctx[tc]) {
641 vsi_ctx->rdma_q_ctx[tc] = (struct ice_q_ctx *)
642 ice_calloc(hw, new_numqs, sizeof(*q_ctx));
643 if (!vsi_ctx->rdma_q_ctx[tc])
644 return ICE_ERR_NO_MEMORY;
645 vsi_ctx->num_rdma_q_entries[tc] = new_numqs;
646 return ICE_SUCCESS;
647 }
648 /* num queues are increased, update the queue contexts */
649 if (new_numqs > vsi_ctx->num_rdma_q_entries[tc]) {
650 u16 prev_num = vsi_ctx->num_rdma_q_entries[tc];
651
652 q_ctx = (struct ice_q_ctx *)
653 ice_calloc(hw, new_numqs, sizeof(*q_ctx));
654 if (!q_ctx)
655 return ICE_ERR_NO_MEMORY;
656 ice_memcpy(q_ctx, vsi_ctx->rdma_q_ctx[tc],
657 prev_num * sizeof(*q_ctx), ICE_DMA_TO_NONDMA);
658 ice_free(hw, vsi_ctx->rdma_q_ctx[tc]);
659 vsi_ctx->rdma_q_ctx[tc] = q_ctx;
660 vsi_ctx->num_rdma_q_entries[tc] = new_numqs;
661 }
662 return ICE_SUCCESS;
663 }
664
665 /**
666 * ice_aq_rl_profile - performs a rate limiting task
667 * @hw: pointer to the HW struct
668 * @opcode: opcode for add, query, or remove profile(s)
669 * @num_profiles: the number of profiles
670 * @buf: pointer to buffer
671 * @buf_size: buffer size in bytes
672 * @num_processed: number of processed add or remove profile(s) to return
673 * @cd: pointer to command details structure
674 *
675 * RL profile function to add, query, or remove profile(s)
676 */
677 static enum ice_status
678 ice_aq_rl_profile(struct ice_hw *hw, enum ice_adminq_opc opcode,
679 u16 num_profiles, struct ice_aqc_rl_profile_elem *buf,
680 u16 buf_size, u16 *num_processed, struct ice_sq_cd *cd)
681 {
682 struct ice_aqc_rl_profile *cmd;
683 struct ice_aq_desc desc;
684 enum ice_status status;
685
686 cmd = &desc.params.rl_profile;
687
688 ice_fill_dflt_direct_cmd_desc(&desc, opcode);
689 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
690 cmd->num_profiles = CPU_TO_LE16(num_profiles);
691 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
692 if (!status && num_processed)
693 *num_processed = LE16_TO_CPU(cmd->num_processed);
694 return status;
695 }
696
697 /**
698 * ice_aq_add_rl_profile - adds rate limiting profile(s)
699 * @hw: pointer to the HW struct
700 * @num_profiles: the number of profile(s) to be add
701 * @buf: pointer to buffer
702 * @buf_size: buffer size in bytes
703 * @num_profiles_added: total number of profiles added to return
704 * @cd: pointer to command details structure
705 *
706 * Add RL profile (0x0410)
707 */
708 static enum ice_status
709 ice_aq_add_rl_profile(struct ice_hw *hw, u16 num_profiles,
710 struct ice_aqc_rl_profile_elem *buf, u16 buf_size,
711 u16 *num_profiles_added, struct ice_sq_cd *cd)
712 {
713 return ice_aq_rl_profile(hw, ice_aqc_opc_add_rl_profiles, num_profiles,
714 buf, buf_size, num_profiles_added, cd);
715 }
716
717 /**
718 * ice_aq_query_rl_profile - query rate limiting profile(s)
719 * @hw: pointer to the HW struct
720 * @num_profiles: the number of profile(s) to query
721 * @buf: pointer to buffer
722 * @buf_size: buffer size in bytes
723 * @cd: pointer to command details structure
724 *
725 * Query RL profile (0x0411)
726 */
727 enum ice_status
728 ice_aq_query_rl_profile(struct ice_hw *hw, u16 num_profiles,
729 struct ice_aqc_rl_profile_elem *buf, u16 buf_size,
730 struct ice_sq_cd *cd)
731 {
732 return ice_aq_rl_profile(hw, ice_aqc_opc_query_rl_profiles,
733 num_profiles, buf, buf_size, NULL, cd);
734 }
735
736 /**
737 * ice_aq_remove_rl_profile - removes RL profile(s)
738 * @hw: pointer to the HW struct
739 * @num_profiles: the number of profile(s) to remove
740 * @buf: pointer to buffer
741 * @buf_size: buffer size in bytes
742 * @num_profiles_removed: total number of profiles removed to return
743 * @cd: pointer to command details structure or NULL
744 *
745 * Remove RL profile (0x0415)
746 */
747 static enum ice_status
748 ice_aq_remove_rl_profile(struct ice_hw *hw, u16 num_profiles,
749 struct ice_aqc_rl_profile_elem *buf, u16 buf_size,
750 u16 *num_profiles_removed, struct ice_sq_cd *cd)
751 {
752 return ice_aq_rl_profile(hw, ice_aqc_opc_remove_rl_profiles,
753 num_profiles, buf, buf_size,
754 num_profiles_removed, cd);
755 }
756
757 /**
758 * ice_sched_del_rl_profile - remove RL profile
759 * @hw: pointer to the HW struct
760 * @rl_info: rate limit profile information
761 *
762 * If the profile ID is not referenced anymore, it removes profile ID with
763 * its associated parameters from HW DB,and locally. The caller needs to
764 * hold scheduler lock.
765 */
766 static enum ice_status
767 ice_sched_del_rl_profile(struct ice_hw *hw,
768 struct ice_aqc_rl_profile_info *rl_info)
769 {
770 struct ice_aqc_rl_profile_elem *buf;
771 u16 num_profiles_removed;
772 enum ice_status status;
773 u16 num_profiles = 1;
774
775 if (rl_info->prof_id_ref != 0)
776 return ICE_ERR_IN_USE;
777
778 /* Safe to remove profile ID */
779 buf = &rl_info->profile;
780 status = ice_aq_remove_rl_profile(hw, num_profiles, buf, sizeof(*buf),
781 &num_profiles_removed, NULL);
782 if (status || num_profiles_removed != num_profiles)
783 return ICE_ERR_CFG;
784
785 /* Delete stale entry now */
786 LIST_DEL(&rl_info->list_entry);
787 ice_free(hw, rl_info);
788 return status;
789 }
790
791 /**
792 * ice_sched_clear_rl_prof - clears RL prof entries
793 * @pi: port information structure
794 *
795 * This function removes all RL profile from HW as well as from SW DB.
796 */
797 static void ice_sched_clear_rl_prof(struct ice_port_info *pi)
798 {
799 u16 ln;
800 struct ice_hw *hw = pi->hw;
801
802 for (ln = 0; ln < hw->num_tx_sched_layers; ln++) {
803 struct ice_aqc_rl_profile_info *rl_prof_elem;
804 struct ice_aqc_rl_profile_info *rl_prof_tmp;
805
806 LIST_FOR_EACH_ENTRY_SAFE(rl_prof_elem, rl_prof_tmp,
807 &hw->rl_prof_list[ln],
808 ice_aqc_rl_profile_info, list_entry) {
809 enum ice_status status;
810
811 rl_prof_elem->prof_id_ref = 0;
812 status = ice_sched_del_rl_profile(hw, rl_prof_elem);
813 if (status) {
814 ice_debug(hw, ICE_DBG_SCHED, "Remove rl profile failed\n");
815 /* On error, free mem required */
816 LIST_DEL(&rl_prof_elem->list_entry);
817 ice_free(hw, rl_prof_elem);
818 }
819 }
820 }
821 }
822
823 /**
824 * ice_sched_clear_agg - clears the aggregator related information
825 * @hw: pointer to the hardware structure
826 *
827 * This function removes aggregator list and free up aggregator related memory
828 * previously allocated.
829 */
830 void ice_sched_clear_agg(struct ice_hw *hw)
831 {
832 struct ice_sched_agg_info *agg_info;
833 struct ice_sched_agg_info *atmp;
834
835 LIST_FOR_EACH_ENTRY_SAFE(agg_info, atmp, &hw->agg_list,
836 ice_sched_agg_info,
837 list_entry) {
838 struct ice_sched_agg_vsi_info *agg_vsi_info;
839 struct ice_sched_agg_vsi_info *vtmp;
840
841 LIST_FOR_EACH_ENTRY_SAFE(agg_vsi_info, vtmp,
842 &agg_info->agg_vsi_list,
843 ice_sched_agg_vsi_info, list_entry) {
844 LIST_DEL(&agg_vsi_info->list_entry);
845 ice_free(hw, agg_vsi_info);
846 }
847 LIST_DEL(&agg_info->list_entry);
848 ice_free(hw, agg_info);
849 }
850 }
851
852 /**
853 * ice_sched_clear_tx_topo - clears the scheduler tree nodes
854 * @pi: port information structure
855 *
856 * This function removes all the nodes from HW as well as from SW DB.
857 */
858 static void ice_sched_clear_tx_topo(struct ice_port_info *pi)
859 {
860 if (!pi)
861 return;
862 /* remove RL profiles related lists */
863 ice_sched_clear_rl_prof(pi);
864 if (pi->root) {
865 ice_free_sched_node(pi, pi->root);
866 pi->root = NULL;
867 }
868 }
869
870 /**
871 * ice_sched_clear_port - clear the scheduler elements from SW DB for a port
872 * @pi: port information structure
873 *
874 * Cleanup scheduling elements from SW DB
875 */
876 void ice_sched_clear_port(struct ice_port_info *pi)
877 {
878 if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY)
879 return;
880
881 pi->port_state = ICE_SCHED_PORT_STATE_INIT;
882 ice_acquire_lock(&pi->sched_lock);
883 ice_sched_clear_tx_topo(pi);
884 ice_release_lock(&pi->sched_lock);
885 ice_destroy_lock(&pi->sched_lock);
886 }
887
888 /**
889 * ice_sched_cleanup_all - cleanup scheduler elements from SW DB for all ports
890 * @hw: pointer to the HW struct
891 *
892 * Cleanup scheduling elements from SW DB for all the ports
893 */
894 void ice_sched_cleanup_all(struct ice_hw *hw)
895 {
896 if (!hw)
897 return;
898
899 if (hw->layer_info) {
900 ice_free(hw, hw->layer_info);
901 hw->layer_info = NULL;
902 }
903
904 ice_sched_clear_port(hw->port_info);
905
906 hw->num_tx_sched_layers = 0;
907 hw->num_tx_sched_phys_layers = 0;
908 hw->flattened_layers = 0;
909 hw->max_cgds = 0;
910 }
911
912 /**
913 * ice_aq_cfg_l2_node_cgd - configures L2 node to CGD mapping
914 * @hw: pointer to the HW struct
915 * @num_l2_nodes: the number of L2 nodes whose CGDs to configure
916 * @buf: pointer to buffer
917 * @buf_size: buffer size in bytes
918 * @cd: pointer to command details structure or NULL
919 *
920 * Configure L2 Node CGD (0x0414)
921 */
922 enum ice_status
923 ice_aq_cfg_l2_node_cgd(struct ice_hw *hw, u16 num_l2_nodes,
924 struct ice_aqc_cfg_l2_node_cgd_elem *buf,
925 u16 buf_size, struct ice_sq_cd *cd)
926 {
927 struct ice_aqc_cfg_l2_node_cgd *cmd;
928 struct ice_aq_desc desc;
929
930 cmd = &desc.params.cfg_l2_node_cgd;
931 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_cfg_l2_node_cgd);
932 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
933
934 cmd->num_l2_nodes = CPU_TO_LE16(num_l2_nodes);
935 return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
936 }
937
938 /**
939 * ice_sched_add_elems - add nodes to HW and SW DB
940 * @pi: port information structure
941 * @tc_node: pointer to the branch node
942 * @parent: pointer to the parent node
943 * @layer: layer number to add nodes
944 * @num_nodes: number of nodes
945 * @num_nodes_added: pointer to num nodes added
946 * @first_node_teid: if new nodes are added then return the TEID of first node
947 *
948 * This function add nodes to HW as well as to SW DB for a given layer
949 */
950 static enum ice_status
951 ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
952 struct ice_sched_node *parent, u8 layer, u16 num_nodes,
953 u16 *num_nodes_added, u32 *first_node_teid)
954 {
955 struct ice_sched_node *prev, *new_node;
956 struct ice_aqc_add_elem *buf;
957 u16 i, num_groups_added = 0;
958 enum ice_status status = ICE_SUCCESS;
959 struct ice_hw *hw = pi->hw;
960 u16 buf_size;
961 u32 teid;
962
963 buf_size = ice_struct_size(buf, generic, num_nodes);
964 buf = (struct ice_aqc_add_elem *)ice_malloc(hw, buf_size);
965 if (!buf)
966 return ICE_ERR_NO_MEMORY;
967
968 buf->hdr.parent_teid = parent->info.node_teid;
969 buf->hdr.num_elems = CPU_TO_LE16(num_nodes);
970 for (i = 0; i < num_nodes; i++) {
971 buf->generic[i].parent_teid = parent->info.node_teid;
972 buf->generic[i].data.elem_type = ICE_AQC_ELEM_TYPE_SE_GENERIC;
973 buf->generic[i].data.valid_sections =
974 ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
975 ICE_AQC_ELEM_VALID_EIR;
976 buf->generic[i].data.generic = 0;
977 buf->generic[i].data.cir_bw.bw_profile_idx =
978 CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
979 buf->generic[i].data.cir_bw.bw_alloc =
980 CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
981 buf->generic[i].data.eir_bw.bw_profile_idx =
982 CPU_TO_LE16(ICE_SCHED_DFLT_RL_PROF_ID);
983 buf->generic[i].data.eir_bw.bw_alloc =
984 CPU_TO_LE16(ICE_SCHED_DFLT_BW_WT);
985 }
986
987 status = ice_aq_add_sched_elems(hw, 1, buf, buf_size,
988 &num_groups_added, NULL);
989 if (status != ICE_SUCCESS || num_groups_added != 1) {
990 ice_debug(hw, ICE_DBG_SCHED, "add node failed FW Error %d\n",
991 hw->adminq.sq_last_status);
992 ice_free(hw, buf);
993 return ICE_ERR_CFG;
994 }
995
996 *num_nodes_added = num_nodes;
997 /* add nodes to the SW DB */
998 for (i = 0; i < num_nodes; i++) {
999 status = ice_sched_add_node(pi, layer, &buf->generic[i]);
1000 if (status != ICE_SUCCESS) {
1001 ice_debug(hw, ICE_DBG_SCHED, "add nodes in SW DB failed status =%d\n",
1002 status);
1003 break;
1004 }
1005
1006 teid = LE32_TO_CPU(buf->generic[i].node_teid);
1007 new_node = ice_sched_find_node_by_teid(parent, teid);
1008 if (!new_node) {
1009 ice_debug(hw, ICE_DBG_SCHED, "Node is missing for teid =%d\n", teid);
1010 break;
1011 }
1012
1013 new_node->sibling = NULL;
1014 new_node->tc_num = tc_node->tc_num;
1015
1016 /* add it to previous node sibling pointer */
1017 /* Note: siblings are not linked across branches */
1018 prev = ice_sched_get_first_node(pi, tc_node, layer);
1019 if (prev && prev != new_node) {
1020 while (prev->sibling)
1021 prev = prev->sibling;
1022 prev->sibling = new_node;
1023 }
1024
1025 /* initialize the sibling head */
1026 if (!pi->sib_head[tc_node->tc_num][layer])
1027 pi->sib_head[tc_node->tc_num][layer] = new_node;
1028
1029 if (i == 0)
1030 *first_node_teid = teid;
1031 }
1032
1033 ice_free(hw, buf);
1034 return status;
1035 }
1036
1037 /**
1038 * ice_sched_add_nodes_to_hw_layer - Add nodes to hw layer
1039 * @pi: port information structure
1040 * @tc_node: pointer to TC node
1041 * @parent: pointer to parent node
1042 * @layer: layer number to add nodes
1043 * @num_nodes: number of nodes to be added
1044 * @first_node_teid: pointer to the first node TEID
1045 * @num_nodes_added: pointer to number of nodes added
1046 *
1047 * Add nodes into specific hw layer.
1048 */
1049 static enum ice_status
1050 ice_sched_add_nodes_to_hw_layer(struct ice_port_info *pi,
1051 struct ice_sched_node *tc_node,
1052 struct ice_sched_node *parent, u8 layer,
1053 u16 num_nodes, u32 *first_node_teid,
1054 u16 *num_nodes_added)
1055 {
1056 u16 max_child_nodes;
1057
1058 *num_nodes_added = 0;
1059
1060 if (!num_nodes)
1061 return ICE_SUCCESS;
1062
1063 if (!parent || layer < pi->hw->sw_entry_point_layer)
1064 return ICE_ERR_PARAM;
1065
1066 /* max children per node per layer */
1067 max_child_nodes = pi->hw->max_children[parent->tx_sched_layer];
1068
1069 /* current number of children + required nodes exceed max children */
1070 if ((parent->num_children + num_nodes) > max_child_nodes) {
1071 /* Fail if the parent is a TC node */
1072 if (parent == tc_node)
1073 return ICE_ERR_CFG;
1074 return ICE_ERR_MAX_LIMIT;
1075 }
1076
1077 return ice_sched_add_elems(pi, tc_node, parent, layer, num_nodes,
1078 num_nodes_added, first_node_teid);
1079 }
1080
1081 /**
1082 * ice_sched_add_nodes_to_layer - Add nodes to a given layer
1083 * @pi: port information structure
1084 * @tc_node: pointer to TC node
1085 * @parent: pointer to parent node
1086 * @layer: layer number to add nodes
1087 * @num_nodes: number of nodes to be added
1088 * @first_node_teid: pointer to the first node TEID
1089 * @num_nodes_added: pointer to number of nodes added
1090 *
1091 * This function add nodes to a given layer.
1092 */
1093 static enum ice_status
1094 ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
1095 struct ice_sched_node *tc_node,
1096 struct ice_sched_node *parent, u8 layer,
1097 u16 num_nodes, u32 *first_node_teid,
1098 u16 *num_nodes_added)
1099 {
1100 u32 *first_teid_ptr = first_node_teid;
1101 u16 new_num_nodes = num_nodes;
1102 enum ice_status status = ICE_SUCCESS;
1103
1104 *num_nodes_added = 0;
1105 while (*num_nodes_added < num_nodes) {
1106 u16 max_child_nodes, num_added = 0;
1107 u32 temp;
1108
1109 status = ice_sched_add_nodes_to_hw_layer(pi, tc_node, parent,
1110 layer, new_num_nodes,
1111 first_teid_ptr,
1112 &num_added);
1113 if (status == ICE_SUCCESS)
1114 *num_nodes_added += num_added;
1115 /* added more nodes than requested ? */
1116 if (*num_nodes_added > num_nodes) {
1117 ice_debug(pi->hw, ICE_DBG_SCHED, "added extra nodes %d %d\n", num_nodes,
1118 *num_nodes_added);
1119 status = ICE_ERR_CFG;
1120 break;
1121 }
1122 /* break if all the nodes are added successfully */
1123 if (status == ICE_SUCCESS && (*num_nodes_added == num_nodes))
1124 break;
1125 /* break if the error is not max limit */
1126 if (status != ICE_SUCCESS && status != ICE_ERR_MAX_LIMIT)
1127 break;
1128 /* Exceeded the max children */
1129 max_child_nodes = pi->hw->max_children[parent->tx_sched_layer];
1130 /* utilize all the spaces if the parent is not full */
1131 if (parent->num_children < max_child_nodes) {
1132 new_num_nodes = max_child_nodes - parent->num_children;
1133 } else {
1134 /* This parent is full, try the next sibling */
1135 parent = parent->sibling;
1136 /* Don't modify the first node TEID memory if the
1137 * first node was added already in the above call.
1138 * Instead send some temp memory for all other
1139 * recursive calls.
1140 */
1141 if (num_added)
1142 first_teid_ptr = &temp;
1143
1144 new_num_nodes = num_nodes - *num_nodes_added;
1145 }
1146 }
1147 return status;
1148 }
1149
1150 /**
1151 * ice_sched_get_qgrp_layer - get the current queue group layer number
1152 * @hw: pointer to the HW struct
1153 *
1154 * This function returns the current queue group layer number
1155 */
1156 static u8 ice_sched_get_qgrp_layer(struct ice_hw *hw)
1157 {
1158 /* It's always total layers - 1, the array is 0 relative so -2 */
1159 return hw->num_tx_sched_layers - ICE_QGRP_LAYER_OFFSET;
1160 }
1161
1162 /**
1163 * ice_sched_get_vsi_layer - get the current VSI layer number
1164 * @hw: pointer to the HW struct
1165 *
1166 * This function returns the current VSI layer number
1167 */
1168 static u8 ice_sched_get_vsi_layer(struct ice_hw *hw)
1169 {
1170 /* Num Layers VSI layer
1171 * 9 6
1172 * 7 4
1173 * 5 or less sw_entry_point_layer
1174 */
1175 /* calculate the VSI layer based on number of layers. */
1176 if (hw->num_tx_sched_layers > ICE_VSI_LAYER_OFFSET + 1) {
1177 u8 layer = hw->num_tx_sched_layers - ICE_VSI_LAYER_OFFSET;
1178
1179 if (layer > hw->sw_entry_point_layer)
1180 return layer;
1181 }
1182 return hw->sw_entry_point_layer;
1183 }
1184
1185 /**
1186 * ice_sched_get_agg_layer - get the current aggregator layer number
1187 * @hw: pointer to the HW struct
1188 *
1189 * This function returns the current aggregator layer number
1190 */
1191 static u8 ice_sched_get_agg_layer(struct ice_hw *hw)
1192 {
1193 /* Num Layers aggregator layer
1194 * 9 4
1195 * 7 or less sw_entry_point_layer
1196 */
1197 /* calculate the aggregator layer based on number of layers. */
1198 if (hw->num_tx_sched_layers > ICE_AGG_LAYER_OFFSET + 1) {
1199 u8 layer = hw->num_tx_sched_layers - ICE_AGG_LAYER_OFFSET;
1200
1201 if (layer > hw->sw_entry_point_layer)
1202 return layer;
1203 }
1204 return hw->sw_entry_point_layer;
1205 }
1206
1207 /**
1208 * ice_rm_dflt_leaf_node - remove the default leaf node in the tree
1209 * @pi: port information structure
1210 *
1211 * This function removes the leaf node that was created by the FW
1212 * during initialization
1213 */
1214 static void ice_rm_dflt_leaf_node(struct ice_port_info *pi)
1215 {
1216 struct ice_sched_node *node;
1217
1218 node = pi->root;
1219 while (node) {
1220 if (!node->num_children)
1221 break;
1222 node = node->children[0];
1223 }
1224 if (node && node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF) {
1225 u32 teid = LE32_TO_CPU(node->info.node_teid);
1226 enum ice_status status;
1227
1228 /* remove the default leaf node */
1229 status = ice_sched_remove_elems(pi->hw, node->parent, 1, &teid);
1230 if (!status)
1231 ice_free_sched_node(pi, node);
1232 }
1233 }
1234
1235 /**
1236 * ice_sched_rm_dflt_nodes - free the default nodes in the tree
1237 * @pi: port information structure
1238 *
1239 * This function frees all the nodes except root and TC that were created by
1240 * the FW during initialization
1241 */
1242 static void ice_sched_rm_dflt_nodes(struct ice_port_info *pi)
1243 {
1244 struct ice_sched_node *node;
1245
1246 ice_rm_dflt_leaf_node(pi);
1247
1248 /* remove the default nodes except TC and root nodes */
1249 node = pi->root;
1250 while (node) {
1251 if (node->tx_sched_layer >= pi->hw->sw_entry_point_layer &&
1252 node->info.data.elem_type != ICE_AQC_ELEM_TYPE_TC &&
1253 node->info.data.elem_type != ICE_AQC_ELEM_TYPE_ROOT_PORT) {
1254 ice_free_sched_node(pi, node);
1255 break;
1256 }
1257
1258 if (!node->num_children)
1259 break;
1260 node = node->children[0];
1261 }
1262 }
1263
1264 /**
1265 * ice_sched_init_port - Initialize scheduler by querying information from FW
1266 * @pi: port info structure for the tree to cleanup
1267 *
1268 * This function is the initial call to find the total number of Tx scheduler
1269 * resources, default topology created by firmware and storing the information
1270 * in SW DB.
1271 */
1272 enum ice_status ice_sched_init_port(struct ice_port_info *pi)
1273 {
1274 struct ice_aqc_get_topo_elem *buf;
1275 enum ice_status status;
1276 struct ice_hw *hw;
1277 u8 num_branches;
1278 u16 num_elems;
1279 u8 i, j;
1280
1281 if (!pi)
1282 return ICE_ERR_PARAM;
1283 hw = pi->hw;
1284
1285 /* Query the Default Topology from FW */
1286 buf = (struct ice_aqc_get_topo_elem *)ice_malloc(hw,
1287 ICE_AQ_MAX_BUF_LEN);
1288 if (!buf)
1289 return ICE_ERR_NO_MEMORY;
1290
1291 /* Query default scheduling tree topology */
1292 status = ice_aq_get_dflt_topo(hw, pi->lport, buf, ICE_AQ_MAX_BUF_LEN,
1293 &num_branches, NULL);
1294 if (status)
1295 goto err_init_port;
1296
1297 /* num_branches should be between 1-8 */
1298 if (num_branches < 1 || num_branches > ICE_TXSCHED_MAX_BRANCHES) {
1299 ice_debug(hw, ICE_DBG_SCHED, "num_branches unexpected %d\n",
1300 num_branches);
1301 status = ICE_ERR_PARAM;
1302 goto err_init_port;
1303 }
1304
1305 /* get the number of elements on the default/first branch */
1306 num_elems = LE16_TO_CPU(buf[0].hdr.num_elems);
1307
1308 /* num_elems should always be between 1-9 */
1309 if (num_elems < 1 || num_elems > ICE_AQC_TOPO_MAX_LEVEL_NUM) {
1310 ice_debug(hw, ICE_DBG_SCHED, "num_elems unexpected %d\n",
1311 num_elems);
1312 status = ICE_ERR_PARAM;
1313 goto err_init_port;
1314 }
1315
1316 /* If the last node is a leaf node then the index of the queue group
1317 * layer is two less than the number of elements.
1318 */
1319 if (num_elems > 2 && buf[0].generic[num_elems - 1].data.elem_type ==
1320 ICE_AQC_ELEM_TYPE_LEAF)
1321 pi->last_node_teid =
1322 LE32_TO_CPU(buf[0].generic[num_elems - 2].node_teid);
1323 else
1324 pi->last_node_teid =
1325 LE32_TO_CPU(buf[0].generic[num_elems - 1].node_teid);
1326
1327 /* Insert the Tx Sched root node */
1328 status = ice_sched_add_root_node(pi, &buf[0].generic[0]);
1329 if (status)
1330 goto err_init_port;
1331
1332 /* Parse the default tree and cache the information */
1333 for (i = 0; i < num_branches; i++) {
1334 num_elems = LE16_TO_CPU(buf[i].hdr.num_elems);
1335
1336 /* Skip root element as already inserted */
1337 for (j = 1; j < num_elems; j++) {
1338 /* update the sw entry point */
1339 if (buf[0].generic[j].data.elem_type ==
1340 ICE_AQC_ELEM_TYPE_ENTRY_POINT)
1341 hw->sw_entry_point_layer = j;
1342
1343 status = ice_sched_add_node(pi, j, &buf[i].generic[j]);
1344 if (status)
1345 goto err_init_port;
1346 }
1347 }
1348
1349 /* Remove the default nodes. */
1350 if (pi->root)
1351 ice_sched_rm_dflt_nodes(pi);
1352
1353 /* initialize the port for handling the scheduler tree */
1354 pi->port_state = ICE_SCHED_PORT_STATE_READY;
1355 ice_init_lock(&pi->sched_lock);
1356 for (i = 0; i < ICE_AQC_TOPO_MAX_LEVEL_NUM; i++)
1357 INIT_LIST_HEAD(&hw->rl_prof_list[i]);
1358
1359 err_init_port:
1360 if (status && pi->root) {
1361 ice_free_sched_node(pi, pi->root);
1362 pi->root = NULL;
1363 }
1364
1365 ice_free(hw, buf);
1366 return status;
1367 }
1368
1369 /**
1370 * ice_sched_get_node - Get the struct ice_sched_node for given TEID
1371 * @pi: port information structure
1372 * @teid: Scheduler node TEID
1373 *
1374 * This function retrieves the ice_sched_node struct for given TEID from
1375 * the SW DB and returns it to the caller.
1376 */
1377 struct ice_sched_node *ice_sched_get_node(struct ice_port_info *pi, u32 teid)
1378 {
1379 struct ice_sched_node *node;
1380
1381 if (!pi)
1382 return NULL;
1383
1384 /* Find the node starting from root */
1385 ice_acquire_lock(&pi->sched_lock);
1386 node = ice_sched_find_node_by_teid(pi->root, teid);
1387 ice_release_lock(&pi->sched_lock);
1388
1389 if (!node)
1390 ice_debug(pi->hw, ICE_DBG_SCHED, "Node not found for teid=0x%x\n", teid);
1391
1392 return node;
1393 }
1394
1395 /**
1396 * ice_sched_query_res_alloc - query the FW for num of logical sched layers
1397 * @hw: pointer to the HW struct
1398 *
1399 * query FW for allocated scheduler resources and store in HW struct
1400 */
1401 enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
1402 {
1403 struct ice_aqc_query_txsched_res_resp *buf;
1404 enum ice_status status = ICE_SUCCESS;
1405 __le16 max_sibl;
1406 u8 i;
1407
1408 if (hw->layer_info)
1409 return status;
1410
1411 buf = (struct ice_aqc_query_txsched_res_resp *)
1412 ice_malloc(hw, sizeof(*buf));
1413 if (!buf)
1414 return ICE_ERR_NO_MEMORY;
1415
1416 status = ice_aq_query_sched_res(hw, sizeof(*buf), buf, NULL);
1417 if (status)
1418 goto sched_query_out;
1419
1420 hw->num_tx_sched_layers = LE16_TO_CPU(buf->sched_props.logical_levels);
1421 hw->num_tx_sched_phys_layers =
1422 LE16_TO_CPU(buf->sched_props.phys_levels);
1423 hw->flattened_layers = buf->sched_props.flattening_bitmap;
1424 hw->max_cgds = buf->sched_props.max_pf_cgds;
1425
1426 /* max sibling group size of current layer refers to the max children
1427 * of the below layer node.
1428 * layer 1 node max children will be layer 2 max sibling group size
1429 * layer 2 node max children will be layer 3 max sibling group size
1430 * and so on. This array will be populated from root (index 0) to
1431 * qgroup layer 7. Leaf node has no children.
1432 */
1433 for (i = 0; i < hw->num_tx_sched_layers - 1; i++) {
1434 max_sibl = buf->layer_props[i + 1].max_sibl_grp_sz;
1435 hw->max_children[i] = LE16_TO_CPU(max_sibl);
1436 }
1437
1438 hw->layer_info = (struct ice_aqc_layer_props *)
1439 ice_memdup(hw, buf->layer_props,
1440 (hw->num_tx_sched_layers *
1441 sizeof(*hw->layer_info)),
1442 ICE_NONDMA_TO_NONDMA);
1443 if (!hw->layer_info) {
1444 status = ICE_ERR_NO_MEMORY;
1445 goto sched_query_out;
1446 }
1447
1448 sched_query_out:
1449 ice_free(hw, buf);
1450 return status;
1451 }
1452
1453 /**
1454 * ice_sched_get_psm_clk_freq - determine the PSM clock frequency
1455 * @hw: pointer to the HW struct
1456 *
1457 * Determine the PSM clock frequency and store in HW struct
1458 */
1459 void ice_sched_get_psm_clk_freq(struct ice_hw *hw)
1460 {
1461 u32 val, clk_src;
1462
1463 val = rd32(hw, GLGEN_CLKSTAT_SRC);
1464 clk_src = (val & GLGEN_CLKSTAT_SRC_PSM_CLK_SRC_M) >>
1465 GLGEN_CLKSTAT_SRC_PSM_CLK_SRC_S;
1466
1467 #define PSM_CLK_SRC_367_MHZ 0x0
1468 #define PSM_CLK_SRC_416_MHZ 0x1
1469 #define PSM_CLK_SRC_446_MHZ 0x2
1470 #define PSM_CLK_SRC_390_MHZ 0x3
1471
1472 switch (clk_src) {
1473 case PSM_CLK_SRC_367_MHZ:
1474 hw->psm_clk_freq = ICE_PSM_CLK_367MHZ_IN_HZ;
1475 break;
1476 case PSM_CLK_SRC_416_MHZ:
1477 hw->psm_clk_freq = ICE_PSM_CLK_416MHZ_IN_HZ;
1478 break;
1479 case PSM_CLK_SRC_446_MHZ:
1480 hw->psm_clk_freq = ICE_PSM_CLK_446MHZ_IN_HZ;
1481 break;
1482 case PSM_CLK_SRC_390_MHZ:
1483 hw->psm_clk_freq = ICE_PSM_CLK_390MHZ_IN_HZ;
1484 break;
1485 default:
1486 ice_debug(hw, ICE_DBG_SCHED, "PSM clk_src unexpected %u\n",
1487 clk_src);
1488 /* fall back to a safe default */
1489 hw->psm_clk_freq = ICE_PSM_CLK_446MHZ_IN_HZ;
1490 }
1491 }
1492
1493 /**
1494 * ice_sched_find_node_in_subtree - Find node in part of base node subtree
1495 * @hw: pointer to the HW struct
1496 * @base: pointer to the base node
1497 * @node: pointer to the node to search
1498 *
1499 * This function checks whether a given node is part of the base node
1500 * subtree or not
1501 */
1502 bool
1503 ice_sched_find_node_in_subtree(struct ice_hw *hw, struct ice_sched_node *base,
1504 struct ice_sched_node *node)
1505 {
1506 u8 i;
1507
1508 for (i = 0; i < base->num_children; i++) {
1509 struct ice_sched_node *child = base->children[i];
1510
1511 if (node == child)
1512 return true;
1513
1514 if (child->tx_sched_layer > node->tx_sched_layer)
1515 return false;
1516
1517 /* this recursion is intentional, and wouldn't
1518 * go more than 8 calls
1519 */
1520 if (ice_sched_find_node_in_subtree(hw, child, node))
1521 return true;
1522 }
1523 return false;
1524 }
1525
1526 /**
1527 * ice_sched_get_free_qgrp - Scan all queue group siblings and find a free node
1528 * @pi: port information structure
1529 * @vsi_node: software VSI handle
1530 * @qgrp_node: first queue group node identified for scanning
1531 * @owner: LAN or RDMA
1532 *
1533 * This function retrieves a free LAN or RDMA queue group node by scanning
1534 * qgrp_node and its siblings for the queue group with the fewest number
1535 * of queues currently assigned.
1536 */
1537 static struct ice_sched_node *
1538 ice_sched_get_free_qgrp(struct ice_port_info *pi,
1539 struct ice_sched_node *vsi_node,
1540 struct ice_sched_node *qgrp_node, u8 owner)
1541 {
1542 struct ice_sched_node *min_qgrp;
1543 u8 min_children;
1544
1545 if (!qgrp_node)
1546 return qgrp_node;
1547 min_children = qgrp_node->num_children;
1548 if (!min_children)
1549 return qgrp_node;
1550 min_qgrp = qgrp_node;
1551 /* scan all queue groups until find a node which has less than the
1552 * minimum number of children. This way all queue group nodes get
1553 * equal number of shares and active. The bandwidth will be equally
1554 * distributed across all queues.
1555 */
1556 while (qgrp_node) {
1557 /* make sure the qgroup node is part of the VSI subtree */
1558 if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
1559 if (qgrp_node->num_children < min_children &&
1560 qgrp_node->owner == owner) {
1561 /* replace the new min queue group node */
1562 min_qgrp = qgrp_node;
1563 min_children = min_qgrp->num_children;
1564 /* break if it has no children, */
1565 if (!min_children)
1566 break;
1567 }
1568 qgrp_node = qgrp_node->sibling;
1569 }
1570 return min_qgrp;
1571 }
1572
1573 /**
1574 * ice_sched_get_free_qparent - Get a free LAN or RDMA queue group node
1575 * @pi: port information structure
1576 * @vsi_handle: software VSI handle
1577 * @tc: branch number
1578 * @owner: LAN or RDMA
1579 *
1580 * This function retrieves a free LAN or RDMA queue group node
1581 */
1582 struct ice_sched_node *
1583 ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
1584 u8 owner)
1585 {
1586 struct ice_sched_node *vsi_node, *qgrp_node;
1587 struct ice_vsi_ctx *vsi_ctx;
1588 u16 max_children;
1589 u8 qgrp_layer;
1590
1591 qgrp_layer = ice_sched_get_qgrp_layer(pi->hw);
1592 max_children = pi->hw->max_children[qgrp_layer];
1593
1594 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
1595 if (!vsi_ctx)
1596 return NULL;
1597 vsi_node = vsi_ctx->sched.vsi_node[tc];
1598 /* validate invalid VSI ID */
1599 if (!vsi_node)
1600 return NULL;
1601
1602 /* get the first queue group node from VSI sub-tree */
1603 qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer);
1604 while (qgrp_node) {
1605 /* make sure the qgroup node is part of the VSI subtree */
1606 if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
1607 if (qgrp_node->num_children < max_children &&
1608 qgrp_node->owner == owner)
1609 break;
1610 qgrp_node = qgrp_node->sibling;
1611 }
1612
1613 /* Select the best queue group */
1614 return ice_sched_get_free_qgrp(pi, vsi_node, qgrp_node, owner);
1615 }
1616
1617 /**
1618 * ice_sched_get_vsi_node - Get a VSI node based on VSI ID
1619 * @pi: pointer to the port information structure
1620 * @tc_node: pointer to the TC node
1621 * @vsi_handle: software VSI handle
1622 *
1623 * This function retrieves a VSI node for a given VSI ID from a given
1624 * TC branch
1625 */
1626 struct ice_sched_node *
1627 ice_sched_get_vsi_node(struct ice_port_info *pi, struct ice_sched_node *tc_node,
1628 u16 vsi_handle)
1629 {
1630 struct ice_sched_node *node;
1631 u8 vsi_layer;
1632
1633 vsi_layer = ice_sched_get_vsi_layer(pi->hw);
1634 node = ice_sched_get_first_node(pi, tc_node, vsi_layer);
1635
1636 /* Check whether it already exists */
1637 while (node) {
1638 if (node->vsi_handle == vsi_handle)
1639 return node;
1640 node = node->sibling;
1641 }
1642
1643 return node;
1644 }
1645
1646 /**
1647 * ice_sched_get_agg_node - Get an aggregator node based on aggregator ID
1648 * @pi: pointer to the port information structure
1649 * @tc_node: pointer to the TC node
1650 * @agg_id: aggregator ID
1651 *
1652 * This function retrieves an aggregator node for a given aggregator ID from
1653 * a given TC branch
1654 */
1655 static struct ice_sched_node *
1656 ice_sched_get_agg_node(struct ice_port_info *pi, struct ice_sched_node *tc_node,
1657 u32 agg_id)
1658 {
1659 struct ice_sched_node *node;
1660 struct ice_hw *hw = pi->hw;
1661 u8 agg_layer;
1662
1663 if (!hw)
1664 return NULL;
1665 agg_layer = ice_sched_get_agg_layer(hw);
1666 node = ice_sched_get_first_node(pi, tc_node, agg_layer);
1667
1668 /* Check whether it already exists */
1669 while (node) {
1670 if (node->agg_id == agg_id)
1671 return node;
1672 node = node->sibling;
1673 }
1674
1675 return node;
1676 }
1677
1678 /**
1679 * ice_sched_check_node - Compare node parameters between SW DB and HW DB
1680 * @hw: pointer to the HW struct
1681 * @node: pointer to the ice_sched_node struct
1682 *
1683 * This function queries and compares the HW element with SW DB node parameters
1684 */
1685 static bool ice_sched_check_node(struct ice_hw *hw, struct ice_sched_node *node)
1686 {
1687 struct ice_aqc_txsched_elem_data buf;
1688 enum ice_status status;
1689 u32 node_teid;
1690
1691 node_teid = LE32_TO_CPU(node->info.node_teid);
1692 status = ice_sched_query_elem(hw, node_teid, &buf);
1693 if (status != ICE_SUCCESS)
1694 return false;
1695
1696 if (memcmp(&buf, &node->info, sizeof(buf))) {
1697 ice_debug(hw, ICE_DBG_SCHED, "Node mismatch for teid=0x%x\n",
1698 node_teid);
1699 return false;
1700 }
1701
1702 return true;
1703 }
1704
1705 /**
1706 * ice_sched_calc_vsi_child_nodes - calculate number of VSI child nodes
1707 * @hw: pointer to the HW struct
1708 * @num_qs: number of queues
1709 * @num_nodes: num nodes array
1710 *
1711 * This function calculates the number of VSI child nodes based on the
1712 * number of queues.
1713 */
1714 static void
1715 ice_sched_calc_vsi_child_nodes(struct ice_hw *hw, u16 num_qs, u16 *num_nodes)
1716 {
1717 u16 num = num_qs;
1718 u8 i, qgl, vsil;
1719
1720 qgl = ice_sched_get_qgrp_layer(hw);
1721 vsil = ice_sched_get_vsi_layer(hw);
1722
1723 /* calculate num nodes from queue group to VSI layer */
1724 for (i = qgl; i > vsil; i--) {
1725 /* round to the next integer if there is a remainder */
1726 num = DIVIDE_AND_ROUND_UP(num, hw->max_children[i]);
1727
1728 /* need at least one node */
1729 num_nodes[i] = num ? num : 1;
1730 }
1731 }
1732
1733 /**
1734 * ice_sched_add_vsi_child_nodes - add VSI child nodes to tree
1735 * @pi: port information structure
1736 * @vsi_handle: software VSI handle
1737 * @tc_node: pointer to the TC node
1738 * @num_nodes: pointer to the num nodes that needs to be added per layer
1739 * @owner: node owner (LAN or RDMA)
1740 *
1741 * This function adds the VSI child nodes to tree. It gets called for
1742 * LAN and RDMA separately.
1743 */
1744 static enum ice_status
1745 ice_sched_add_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_handle,
1746 struct ice_sched_node *tc_node, u16 *num_nodes,
1747 u8 owner)
1748 {
1749 struct ice_sched_node *parent, *node;
1750 struct ice_hw *hw = pi->hw;
1751 enum ice_status status;
1752 u32 first_node_teid;
1753 u16 num_added = 0;
1754 u8 i, qgl, vsil;
1755
1756 qgl = ice_sched_get_qgrp_layer(hw);
1757 vsil = ice_sched_get_vsi_layer(hw);
1758 parent = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
1759 for (i = vsil + 1; i <= qgl; i++) {
1760 if (!parent)
1761 return ICE_ERR_CFG;
1762
1763 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent, i,
1764 num_nodes[i],
1765 &first_node_teid,
1766 &num_added);
1767 if (status != ICE_SUCCESS || num_nodes[i] != num_added)
1768 return ICE_ERR_CFG;
1769
1770 /* The newly added node can be a new parent for the next
1771 * layer nodes
1772 */
1773 if (num_added) {
1774 parent = ice_sched_find_node_by_teid(tc_node,
1775 first_node_teid);
1776 node = parent;
1777 while (node) {
1778 node->owner = owner;
1779 node = node->sibling;
1780 }
1781 } else {
1782 parent = parent->children[0];
1783 }
1784 }
1785
1786 return ICE_SUCCESS;
1787 }
1788
1789 /**
1790 * ice_sched_calc_vsi_support_nodes - calculate number of VSI support nodes
1791 * @pi: pointer to the port info structure
1792 * @tc_node: pointer to TC node
1793 * @num_nodes: pointer to num nodes array
1794 *
1795 * This function calculates the number of supported nodes needed to add this
1796 * VSI into Tx tree including the VSI, parent and intermediate nodes in below
1797 * layers
1798 */
1799 static void
1800 ice_sched_calc_vsi_support_nodes(struct ice_port_info *pi,
1801 struct ice_sched_node *tc_node, u16 *num_nodes)
1802 {
1803 struct ice_sched_node *node;
1804 u8 vsil;
1805 int i;
1806
1807 vsil = ice_sched_get_vsi_layer(pi->hw);
1808 for (i = vsil; i >= pi->hw->sw_entry_point_layer; i--)
1809 /* Add intermediate nodes if TC has no children and
1810 * need at least one node for VSI
1811 */
1812 if (!tc_node->num_children || i == vsil) {
1813 num_nodes[i]++;
1814 } else {
1815 /* If intermediate nodes are reached max children
1816 * then add a new one.
1817 */
1818 node = ice_sched_get_first_node(pi, tc_node, (u8)i);
1819 /* scan all the siblings */
1820 while (node) {
1821 if (node->num_children <
1822 pi->hw->max_children[i])
1823 break;
1824 node = node->sibling;
1825 }
1826
1827 /* tree has one intermediate node to add this new VSI.
1828 * So no need to calculate supported nodes for below
1829 * layers.
1830 */
1831 if (node)
1832 break;
1833 /* all the nodes are full, allocate a new one */
1834 num_nodes[i]++;
1835 }
1836 }
1837
1838 /**
1839 * ice_sched_add_vsi_support_nodes - add VSI supported nodes into Tx tree
1840 * @pi: port information structure
1841 * @vsi_handle: software VSI handle
1842 * @tc_node: pointer to TC node
1843 * @num_nodes: pointer to num nodes array
1844 *
1845 * This function adds the VSI supported nodes into Tx tree including the
1846 * VSI, its parent and intermediate nodes in below layers
1847 */
1848 static enum ice_status
1849 ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_handle,
1850 struct ice_sched_node *tc_node, u16 *num_nodes)
1851 {
1852 struct ice_sched_node *parent = tc_node;
1853 enum ice_status status;
1854 u32 first_node_teid;
1855 u16 num_added = 0;
1856 u8 i, vsil;
1857
1858 if (!pi)
1859 return ICE_ERR_PARAM;
1860
1861 vsil = ice_sched_get_vsi_layer(pi->hw);
1862 for (i = pi->hw->sw_entry_point_layer; i <= vsil; i++) {
1863 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,
1864 i, num_nodes[i],
1865 &first_node_teid,
1866 &num_added);
1867 if (status != ICE_SUCCESS || num_nodes[i] != num_added)
1868 return ICE_ERR_CFG;
1869
1870 /* The newly added node can be a new parent for the next
1871 * layer nodes
1872 */
1873 if (num_added)
1874 parent = ice_sched_find_node_by_teid(tc_node,
1875 first_node_teid);
1876 else
1877 parent = parent->children[0];
1878
1879 if (!parent)
1880 return ICE_ERR_CFG;
1881
1882 if (i == vsil)
1883 parent->vsi_handle = vsi_handle;
1884 }
1885
1886 return ICE_SUCCESS;
1887 }
1888
1889 /**
1890 * ice_sched_add_vsi_to_topo - add a new VSI into tree
1891 * @pi: port information structure
1892 * @vsi_handle: software VSI handle
1893 * @tc: TC number
1894 *
1895 * This function adds a new VSI into scheduler tree
1896 */
1897 static enum ice_status
1898 ice_sched_add_vsi_to_topo(struct ice_port_info *pi, u16 vsi_handle, u8 tc)
1899 {
1900 u16 num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
1901 struct ice_sched_node *tc_node;
1902
1903 tc_node = ice_sched_get_tc_node(pi, tc);
1904 if (!tc_node)
1905 return ICE_ERR_PARAM;
1906
1907 /* calculate number of supported nodes needed for this VSI */
1908 ice_sched_calc_vsi_support_nodes(pi, tc_node, num_nodes);
1909
1910 /* add VSI supported nodes to TC subtree */
1911 return ice_sched_add_vsi_support_nodes(pi, vsi_handle, tc_node,
1912 num_nodes);
1913 }
1914
1915 /**
1916 * ice_sched_update_vsi_child_nodes - update VSI child nodes
1917 * @pi: port information structure
1918 * @vsi_handle: software VSI handle
1919 * @tc: TC number
1920 * @new_numqs: new number of max queues
1921 * @owner: owner of this subtree
1922 *
1923 * This function updates the VSI child nodes based on the number of queues
1924 */
1925 static enum ice_status
1926 ice_sched_update_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_handle,
1927 u8 tc, u16 new_numqs, u8 owner)
1928 {
1929 u16 new_num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
1930 struct ice_sched_node *vsi_node;
1931 struct ice_sched_node *tc_node;
1932 struct ice_vsi_ctx *vsi_ctx;
1933 enum ice_status status = ICE_SUCCESS;
1934 struct ice_hw *hw = pi->hw;
1935 u16 prev_numqs;
1936
1937 tc_node = ice_sched_get_tc_node(pi, tc);
1938 if (!tc_node)
1939 return ICE_ERR_CFG;
1940
1941 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
1942 if (!vsi_node)
1943 return ICE_ERR_CFG;
1944
1945 vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
1946 if (!vsi_ctx)
1947 return ICE_ERR_PARAM;
1948
1949 if (owner == ICE_SCHED_NODE_OWNER_LAN)
1950 prev_numqs = vsi_ctx->sched.max_lanq[tc];
1951 else
1952 prev_numqs = vsi_ctx->sched.max_rdmaq[tc];
1953 /* num queues are not changed or less than the previous number */
1954 if (new_numqs <= prev_numqs)
1955 return status;
1956 if (owner == ICE_SCHED_NODE_OWNER_LAN) {
1957 status = ice_alloc_lan_q_ctx(hw, vsi_handle, tc, new_numqs);
1958 if (status)
1959 return status;
1960 } else {
1961 status = ice_alloc_rdma_q_ctx(hw, vsi_handle, tc, new_numqs);
1962 if (status)
1963 return status;
1964 }
1965
1966 if (new_numqs)
1967 ice_sched_calc_vsi_child_nodes(hw, new_numqs, new_num_nodes);
1968 /* Keep the max number of queue configuration all the time. Update the
1969 * tree only if number of queues > previous number of queues. This may
1970 * leave some extra nodes in the tree if number of queues < previous
1971 * number but that wouldn't harm anything. Removing those extra nodes
1972 * may complicate the code if those nodes are part of SRL or
1973 * individually rate limited.
1974 */
1975 status = ice_sched_add_vsi_child_nodes(pi, vsi_handle, tc_node,
1976 new_num_nodes, owner);
1977 if (status)
1978 return status;
1979 if (owner == ICE_SCHED_NODE_OWNER_LAN)
1980 vsi_ctx->sched.max_lanq[tc] = new_numqs;
1981 else
1982 vsi_ctx->sched.max_rdmaq[tc] = new_numqs;
1983
1984 return ICE_SUCCESS;
1985 }
1986
1987 /**
1988 * ice_sched_cfg_vsi - configure the new/existing VSI
1989 * @pi: port information structure
1990 * @vsi_handle: software VSI handle
1991 * @tc: TC number
1992 * @maxqs: max number of queues
1993 * @owner: LAN or RDMA
1994 * @enable: TC enabled or disabled
1995 *
1996 * This function adds/updates VSI nodes based on the number of queues. If TC is
1997 * enabled and VSI is in suspended state then resume the VSI back. If TC is
1998 * disabled then suspend the VSI if it is not already.
1999 */
2000 enum ice_status
2001 ice_sched_cfg_vsi(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u16 maxqs,
2002 u8 owner, bool enable)
2003 {
2004 struct ice_sched_node *vsi_node, *tc_node;
2005 struct ice_vsi_ctx *vsi_ctx;
2006 enum ice_status status = ICE_SUCCESS;
2007 struct ice_hw *hw = pi->hw;
2008
2009 ice_debug(pi->hw, ICE_DBG_SCHED, "add/config VSI %d\n", vsi_handle);
2010 tc_node = ice_sched_get_tc_node(pi, tc);
2011 if (!tc_node)
2012 return ICE_ERR_PARAM;
2013 vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
2014 if (!vsi_ctx)
2015 return ICE_ERR_PARAM;
2016 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
2017
2018 /* suspend the VSI if TC is not enabled */
2019 if (!enable) {
2020 if (vsi_node && vsi_node->in_use) {
2021 u32 teid = LE32_TO_CPU(vsi_node->info.node_teid);
2022
2023 status = ice_sched_suspend_resume_elems(hw, 1, &teid,
2024 true);
2025 if (!status)
2026 vsi_node->in_use = false;
2027 }
2028 return status;
2029 }
2030
2031 /* TC is enabled, if it is a new VSI then add it to the tree */
2032 if (!vsi_node) {
2033 status = ice_sched_add_vsi_to_topo(pi, vsi_handle, tc);
2034 if (status)
2035 return status;
2036
2037 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
2038 if (!vsi_node)
2039 return ICE_ERR_CFG;
2040
2041 vsi_ctx->sched.vsi_node[tc] = vsi_node;
2042 vsi_node->in_use = true;
2043 /* invalidate the max queues whenever VSI gets added first time
2044 * into the scheduler tree (boot or after reset). We need to
2045 * recreate the child nodes all the time in these cases.
2046 */
2047 vsi_ctx->sched.max_lanq[tc] = 0;
2048 vsi_ctx->sched.max_rdmaq[tc] = 0;
2049 }
2050
2051 /* update the VSI child nodes */
2052 status = ice_sched_update_vsi_child_nodes(pi, vsi_handle, tc, maxqs,
2053 owner);
2054 if (status)
2055 return status;
2056
2057 /* TC is enabled, resume the VSI if it is in the suspend state */
2058 if (!vsi_node->in_use) {
2059 u32 teid = LE32_TO_CPU(vsi_node->info.node_teid);
2060
2061 status = ice_sched_suspend_resume_elems(hw, 1, &teid, false);
2062 if (!status)
2063 vsi_node->in_use = true;
2064 }
2065
2066 return status;
2067 }
2068
2069 /**
2070 * ice_sched_rm_agg_vsi_info - remove aggregator related VSI info entry
2071 * @pi: port information structure
2072 * @vsi_handle: software VSI handle
2073 *
2074 * This function removes single aggregator VSI info entry from
2075 * aggregator list.
2076 */
2077 static void ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle)
2078 {
2079 struct ice_sched_agg_info *agg_info;
2080 struct ice_sched_agg_info *atmp;
2081
2082 LIST_FOR_EACH_ENTRY_SAFE(agg_info, atmp, &pi->hw->agg_list,
2083 ice_sched_agg_info,
2084 list_entry) {
2085 struct ice_sched_agg_vsi_info *agg_vsi_info;
2086 struct ice_sched_agg_vsi_info *vtmp;
2087
2088 LIST_FOR_EACH_ENTRY_SAFE(agg_vsi_info, vtmp,
2089 &agg_info->agg_vsi_list,
2090 ice_sched_agg_vsi_info, list_entry)
2091 if (agg_vsi_info->vsi_handle == vsi_handle) {
2092 LIST_DEL(&agg_vsi_info->list_entry);
2093 ice_free(pi->hw, agg_vsi_info);
2094 return;
2095 }
2096 }
2097 }
2098
2099 /**
2100 * ice_sched_is_leaf_node_present - check for a leaf node in the sub-tree
2101 * @node: pointer to the sub-tree node
2102 *
2103 * This function checks for a leaf node presence in a given sub-tree node.
2104 */
2105 static bool ice_sched_is_leaf_node_present(struct ice_sched_node *node)
2106 {
2107 u8 i;
2108
2109 for (i = 0; i < node->num_children; i++)
2110 if (ice_sched_is_leaf_node_present(node->children[i]))
2111 return true;
2112 /* check for a leaf node */
2113 return (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF);
2114 }
2115
2116 /**
2117 * ice_sched_rm_vsi_cfg - remove the VSI and its children nodes
2118 * @pi: port information structure
2119 * @vsi_handle: software VSI handle
2120 * @owner: LAN or RDMA
2121 *
2122 * This function removes the VSI and its LAN or RDMA children nodes from the
2123 * scheduler tree.
2124 */
2125 static enum ice_status
2126 ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
2127 {
2128 enum ice_status status = ICE_ERR_PARAM;
2129 struct ice_vsi_ctx *vsi_ctx;
2130 u8 i;
2131
2132 ice_debug(pi->hw, ICE_DBG_SCHED, "removing VSI %d\n", vsi_handle);
2133 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
2134 return status;
2135 ice_acquire_lock(&pi->sched_lock);
2136 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
2137 if (!vsi_ctx)
2138 goto exit_sched_rm_vsi_cfg;
2139
2140 ice_for_each_traffic_class(i) {
2141 struct ice_sched_node *vsi_node, *tc_node;
2142 u8 j = 0;
2143
2144 tc_node = ice_sched_get_tc_node(pi, i);
2145 if (!tc_node)
2146 continue;
2147
2148 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
2149 if (!vsi_node)
2150 continue;
2151
2152 if (ice_sched_is_leaf_node_present(vsi_node)) {
2153 ice_debug(pi->hw, ICE_DBG_SCHED, "VSI has leaf nodes in TC %d\n", i);
2154 status = ICE_ERR_IN_USE;
2155 goto exit_sched_rm_vsi_cfg;
2156 }
2157 while (j < vsi_node->num_children) {
2158 if (vsi_node->children[j]->owner == owner) {
2159 ice_free_sched_node(pi, vsi_node->children[j]);
2160
2161 /* reset the counter again since the num
2162 * children will be updated after node removal
2163 */
2164 j = 0;
2165 } else {
2166 j++;
2167 }
2168 }
2169 /* remove the VSI if it has no children */
2170 if (!vsi_node->num_children) {
2171 ice_free_sched_node(pi, vsi_node);
2172 vsi_ctx->sched.vsi_node[i] = NULL;
2173
2174 /* clean up aggregator related VSI info if any */
2175 ice_sched_rm_agg_vsi_info(pi, vsi_handle);
2176 }
2177 if (owner == ICE_SCHED_NODE_OWNER_LAN)
2178 vsi_ctx->sched.max_lanq[i] = 0;
2179 else
2180 vsi_ctx->sched.max_rdmaq[i] = 0;
2181 }
2182 status = ICE_SUCCESS;
2183
2184 exit_sched_rm_vsi_cfg:
2185 ice_release_lock(&pi->sched_lock);
2186 return status;
2187 }
2188
2189 /**
2190 * ice_rm_vsi_lan_cfg - remove VSI and its LAN children nodes
2191 * @pi: port information structure
2192 * @vsi_handle: software VSI handle
2193 *
2194 * This function clears the VSI and its LAN children nodes from scheduler tree
2195 * for all TCs.
2196 */
2197 enum ice_status ice_rm_vsi_lan_cfg(struct ice_port_info *pi, u16 vsi_handle)
2198 {
2199 return ice_sched_rm_vsi_cfg(pi, vsi_handle, ICE_SCHED_NODE_OWNER_LAN);
2200 }
2201
2202 /**
2203 * ice_rm_vsi_rdma_cfg - remove VSI and its RDMA children nodes
2204 * @pi: port information structure
2205 * @vsi_handle: software VSI handle
2206 *
2207 * This function clears the VSI and its RDMA children nodes from scheduler tree
2208 * for all TCs.
2209 */
2210 enum ice_status ice_rm_vsi_rdma_cfg(struct ice_port_info *pi, u16 vsi_handle)
2211 {
2212 return ice_sched_rm_vsi_cfg(pi, vsi_handle, ICE_SCHED_NODE_OWNER_RDMA);
2213 }
2214
2215 /**
2216 * ice_sched_is_tree_balanced - Check tree nodes are identical or not
2217 * @hw: pointer to the HW struct
2218 * @node: pointer to the ice_sched_node struct
2219 *
2220 * This function compares all the nodes for a given tree against HW DB nodes
2221 * This function needs to be called with the port_info->sched_lock held
2222 */
2223 bool ice_sched_is_tree_balanced(struct ice_hw *hw, struct ice_sched_node *node)
2224 {
2225 u8 i;
2226
2227 /* start from the leaf node */
2228 for (i = 0; i < node->num_children; i++)
2229 /* Fail if node doesn't match with the SW DB
2230 * this recursion is intentional, and wouldn't
2231 * go more than 9 calls
2232 */
2233 if (!ice_sched_is_tree_balanced(hw, node->children[i]))
2234 return false;
2235
2236 return ice_sched_check_node(hw, node);
2237 }
2238
2239 /**
2240 * ice_aq_query_node_to_root - retrieve the tree topology for a given node TEID
2241 * @hw: pointer to the HW struct
2242 * @node_teid: node TEID
2243 * @buf: pointer to buffer
2244 * @buf_size: buffer size in bytes
2245 * @cd: pointer to command details structure or NULL
2246 *
2247 * This function retrieves the tree topology from the firmware for a given
2248 * node TEID to the root node.
2249 */
2250 enum ice_status
2251 ice_aq_query_node_to_root(struct ice_hw *hw, u32 node_teid,
2252 struct ice_aqc_txsched_elem_data *buf, u16 buf_size,
2253 struct ice_sq_cd *cd)
2254 {
2255 struct ice_aqc_query_node_to_root *cmd;
2256 struct ice_aq_desc desc;
2257
2258 cmd = &desc.params.query_node_to_root;
2259 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_node_to_root);
2260 cmd->teid = CPU_TO_LE32(node_teid);
2261 return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2262 }
2263
2264 /**
2265 * ice_get_agg_info - get the aggregator ID
2266 * @hw: pointer to the hardware structure
2267 * @agg_id: aggregator ID
2268 *
2269 * This function validates aggregator ID. The function returns info if
2270 * aggregator ID is present in list otherwise it returns null.
2271 */
2272 static struct ice_sched_agg_info *
2273 ice_get_agg_info(struct ice_hw *hw, u32 agg_id)
2274 {
2275 struct ice_sched_agg_info *agg_info;
2276
2277 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
2278 list_entry)
2279 if (agg_info->agg_id == agg_id)
2280 return agg_info;
2281
2282 return NULL;
2283 }
2284
2285 /**
2286 * ice_sched_get_free_vsi_parent - Find a free parent node in aggregator subtree
2287 * @hw: pointer to the HW struct
2288 * @node: pointer to a child node
2289 * @num_nodes: num nodes count array
2290 *
2291 * This function walks through the aggregator subtree to find a free parent
2292 * node
2293 */
2294 static struct ice_sched_node *
2295 ice_sched_get_free_vsi_parent(struct ice_hw *hw, struct ice_sched_node *node,
2296 u16 *num_nodes)
2297 {
2298 u8 l = node->tx_sched_layer;
2299 u8 vsil, i;
2300
2301 vsil = ice_sched_get_vsi_layer(hw);
2302
2303 /* Is it VSI parent layer ? */
2304 if (l == vsil - 1)
2305 return (node->num_children < hw->max_children[l]) ? node : NULL;
2306
2307 /* We have intermediate nodes. Let's walk through the subtree. If the
2308 * intermediate node has space to add a new node then clear the count
2309 */
2310 if (node->num_children < hw->max_children[l])
2311 num_nodes[l] = 0;
2312 /* The below recursive call is intentional and wouldn't go more than
2313 * 2 or 3 iterations.
2314 */
2315
2316 for (i = 0; i < node->num_children; i++) {
2317 struct ice_sched_node *parent;
2318
2319 parent = ice_sched_get_free_vsi_parent(hw, node->children[i],
2320 num_nodes);
2321 if (parent)
2322 return parent;
2323 }
2324
2325 return NULL;
2326 }
2327
2328 /**
2329 * ice_sched_update_parent - update the new parent in SW DB
2330 * @new_parent: pointer to a new parent node
2331 * @node: pointer to a child node
2332 *
2333 * This function removes the child from the old parent and adds it to a new
2334 * parent
2335 */
2336 static void
2337 ice_sched_update_parent(struct ice_sched_node *new_parent,
2338 struct ice_sched_node *node)
2339 {
2340 struct ice_sched_node *old_parent;
2341 u8 i, j;
2342
2343 old_parent = node->parent;
2344
2345 /* update the old parent children */
2346 for (i = 0; i < old_parent->num_children; i++)
2347 if (old_parent->children[i] == node) {
2348 for (j = i + 1; j < old_parent->num_children; j++)
2349 old_parent->children[j - 1] =
2350 old_parent->children[j];
2351 old_parent->num_children--;
2352 break;
2353 }
2354
2355 /* now move the node to a new parent */
2356 new_parent->children[new_parent->num_children++] = node;
2357 node->parent = new_parent;
2358 node->info.parent_teid = new_parent->info.node_teid;
2359 }
2360
2361 /**
2362 * ice_sched_move_nodes - move child nodes to a given parent
2363 * @pi: port information structure
2364 * @parent: pointer to parent node
2365 * @num_items: number of child nodes to be moved
2366 * @list: pointer to child node teids
2367 *
2368 * This function move the child nodes to a given parent.
2369 */
2370 static enum ice_status
2371 ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
2372 u16 num_items, u32 *list)
2373 {
2374 struct ice_aqc_move_elem *buf;
2375 struct ice_sched_node *node;
2376 enum ice_status status = ICE_SUCCESS;
2377 u16 i, grps_movd = 0;
2378 struct ice_hw *hw;
2379 u16 buf_len;
2380
2381 hw = pi->hw;
2382
2383 if (!parent || !num_items)
2384 return ICE_ERR_PARAM;
2385
2386 /* Does parent have enough space */
2387 if (parent->num_children + num_items >
2388 hw->max_children[parent->tx_sched_layer])
2389 return ICE_ERR_AQ_FULL;
2390
2391 buf_len = ice_struct_size(buf, teid, 1);
2392 buf = (struct ice_aqc_move_elem *)ice_malloc(hw, buf_len);
2393 if (!buf)
2394 return ICE_ERR_NO_MEMORY;
2395
2396 for (i = 0; i < num_items; i++) {
2397 node = ice_sched_find_node_by_teid(pi->root, list[i]);
2398 if (!node) {
2399 status = ICE_ERR_PARAM;
2400 goto move_err_exit;
2401 }
2402
2403 buf->hdr.src_parent_teid = node->info.parent_teid;
2404 buf->hdr.dest_parent_teid = parent->info.node_teid;
2405 buf->teid[0] = node->info.node_teid;
2406 buf->hdr.num_elems = CPU_TO_LE16(1);
2407 status = ice_aq_move_sched_elems(hw, 1, buf, buf_len,
2408 &grps_movd, NULL);
2409 if (status && grps_movd != 1) {
2410 status = ICE_ERR_CFG;
2411 goto move_err_exit;
2412 }
2413
2414 /* update the SW DB */
2415 ice_sched_update_parent(parent, node);
2416 }
2417
2418 move_err_exit:
2419 ice_free(hw, buf);
2420 return status;
2421 }
2422
2423 /**
2424 * ice_sched_move_vsi_to_agg - move VSI to aggregator node
2425 * @pi: port information structure
2426 * @vsi_handle: software VSI handle
2427 * @agg_id: aggregator ID
2428 * @tc: TC number
2429 *
2430 * This function moves a VSI to an aggregator node or its subtree.
2431 * Intermediate nodes may be created if required.
2432 */
2433 static enum ice_status
2434 ice_sched_move_vsi_to_agg(struct ice_port_info *pi, u16 vsi_handle, u32 agg_id,
2435 u8 tc)
2436 {
2437 struct ice_sched_node *vsi_node, *agg_node, *tc_node, *parent;
2438 u16 num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
2439 u32 first_node_teid, vsi_teid;
2440 enum ice_status status;
2441 u16 num_nodes_added;
2442 u8 aggl, vsil, i;
2443
2444 tc_node = ice_sched_get_tc_node(pi, tc);
2445 if (!tc_node)
2446 return ICE_ERR_CFG;
2447
2448 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
2449 if (!agg_node)
2450 return ICE_ERR_DOES_NOT_EXIST;
2451
2452 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
2453 if (!vsi_node)
2454 return ICE_ERR_DOES_NOT_EXIST;
2455
2456 /* Is this VSI already part of given aggregator? */
2457 if (ice_sched_find_node_in_subtree(pi->hw, agg_node, vsi_node))
2458 return ICE_SUCCESS;
2459
2460 aggl = ice_sched_get_agg_layer(pi->hw);
2461 vsil = ice_sched_get_vsi_layer(pi->hw);
2462
2463 /* set intermediate node count to 1 between aggregator and VSI layers */
2464 for (i = aggl + 1; i < vsil; i++)
2465 num_nodes[i] = 1;
2466
2467 /* Check if the aggregator subtree has any free node to add the VSI */
2468 for (i = 0; i < agg_node->num_children; i++) {
2469 parent = ice_sched_get_free_vsi_parent(pi->hw,
2470 agg_node->children[i],
2471 num_nodes);
2472 if (parent)
2473 goto move_nodes;
2474 }
2475
2476 /* add new nodes */
2477 parent = agg_node;
2478 for (i = aggl + 1; i < vsil; i++) {
2479 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent, i,
2480 num_nodes[i],
2481 &first_node_teid,
2482 &num_nodes_added);
2483 if (status != ICE_SUCCESS || num_nodes[i] != num_nodes_added)
2484 return ICE_ERR_CFG;
2485
2486 /* The newly added node can be a new parent for the next
2487 * layer nodes
2488 */
2489 if (num_nodes_added)
2490 parent = ice_sched_find_node_by_teid(tc_node,
2491 first_node_teid);
2492 else
2493 parent = parent->children[0];
2494
2495 if (!parent)
2496 return ICE_ERR_CFG;
2497 }
2498
2499 move_nodes:
2500 vsi_teid = LE32_TO_CPU(vsi_node->info.node_teid);
2501 return ice_sched_move_nodes(pi, parent, 1, &vsi_teid);
2502 }
2503
2504 /**
2505 * ice_move_all_vsi_to_dflt_agg - move all VSI(s) to default aggregator
2506 * @pi: port information structure
2507 * @agg_info: aggregator info
2508 * @tc: traffic class number
2509 * @rm_vsi_info: true or false
2510 *
2511 * This function move all the VSI(s) to the default aggregator and delete
2512 * aggregator VSI info based on passed in boolean parameter rm_vsi_info. The
2513 * caller holds the scheduler lock.
2514 */
2515 static enum ice_status
2516 ice_move_all_vsi_to_dflt_agg(struct ice_port_info *pi,
2517 struct ice_sched_agg_info *agg_info, u8 tc,
2518 bool rm_vsi_info)
2519 {
2520 struct ice_sched_agg_vsi_info *agg_vsi_info;
2521 struct ice_sched_agg_vsi_info *tmp;
2522 enum ice_status status = ICE_SUCCESS;
2523
2524 LIST_FOR_EACH_ENTRY_SAFE(agg_vsi_info, tmp, &agg_info->agg_vsi_list,
2525 ice_sched_agg_vsi_info, list_entry) {
2526 u16 vsi_handle = agg_vsi_info->vsi_handle;
2527
2528 /* Move VSI to default aggregator */
2529 if (!ice_is_tc_ena(agg_vsi_info->tc_bitmap[0], tc))
2530 continue;
2531
2532 status = ice_sched_move_vsi_to_agg(pi, vsi_handle,
2533 ICE_DFLT_AGG_ID, tc);
2534 if (status)
2535 break;
2536
2537 ice_clear_bit(tc, agg_vsi_info->tc_bitmap);
2538 if (rm_vsi_info && !agg_vsi_info->tc_bitmap[0]) {
2539 LIST_DEL(&agg_vsi_info->list_entry);
2540 ice_free(pi->hw, agg_vsi_info);
2541 }
2542 }
2543
2544 return status;
2545 }
2546
2547 /**
2548 * ice_sched_is_agg_inuse - check whether the aggregator is in use or not
2549 * @pi: port information structure
2550 * @node: node pointer
2551 *
2552 * This function checks whether the aggregator is attached with any VSI or not.
2553 */
2554 static bool
2555 ice_sched_is_agg_inuse(struct ice_port_info *pi, struct ice_sched_node *node)
2556 {
2557 u8 vsil, i;
2558
2559 vsil = ice_sched_get_vsi_layer(pi->hw);
2560 if (node->tx_sched_layer < vsil - 1) {
2561 for (i = 0; i < node->num_children; i++)
2562 if (ice_sched_is_agg_inuse(pi, node->children[i]))
2563 return true;
2564 return false;
2565 } else {
2566 return node->num_children ? true : false;
2567 }
2568 }
2569
2570 /**
2571 * ice_sched_rm_agg_cfg - remove the aggregator node
2572 * @pi: port information structure
2573 * @agg_id: aggregator ID
2574 * @tc: TC number
2575 *
2576 * This function removes the aggregator node and intermediate nodes if any
2577 * from the given TC
2578 */
2579 static enum ice_status
2580 ice_sched_rm_agg_cfg(struct ice_port_info *pi, u32 agg_id, u8 tc)
2581 {
2582 struct ice_sched_node *tc_node, *agg_node;
2583 struct ice_hw *hw = pi->hw;
2584
2585 tc_node = ice_sched_get_tc_node(pi, tc);
2586 if (!tc_node)
2587 return ICE_ERR_CFG;
2588
2589 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
2590 if (!agg_node)
2591 return ICE_ERR_DOES_NOT_EXIST;
2592
2593 /* Can't remove the aggregator node if it has children */
2594 if (ice_sched_is_agg_inuse(pi, agg_node))
2595 return ICE_ERR_IN_USE;
2596
2597 /* need to remove the whole subtree if aggregator node is the
2598 * only child.
2599 */
2600 while (agg_node->tx_sched_layer > hw->sw_entry_point_layer) {
2601 struct ice_sched_node *parent = agg_node->parent;
2602
2603 if (!parent)
2604 return ICE_ERR_CFG;
2605
2606 if (parent->num_children > 1)
2607 break;
2608
2609 agg_node = parent;
2610 }
2611
2612 ice_free_sched_node(pi, agg_node);
2613 return ICE_SUCCESS;
2614 }
2615
2616 /**
2617 * ice_rm_agg_cfg_tc - remove aggregator configuration for TC
2618 * @pi: port information structure
2619 * @agg_info: aggregator ID
2620 * @tc: TC number
2621 * @rm_vsi_info: bool value true or false
2622 *
2623 * This function removes aggregator reference to VSI of given TC. It removes
2624 * the aggregator configuration completely for requested TC. The caller needs
2625 * to hold the scheduler lock.
2626 */
2627 static enum ice_status
2628 ice_rm_agg_cfg_tc(struct ice_port_info *pi, struct ice_sched_agg_info *agg_info,
2629 u8 tc, bool rm_vsi_info)
2630 {
2631 enum ice_status status = ICE_SUCCESS;
2632
2633 /* If nothing to remove - return success */
2634 if (!ice_is_tc_ena(agg_info->tc_bitmap[0], tc))
2635 goto exit_rm_agg_cfg_tc;
2636
2637 status = ice_move_all_vsi_to_dflt_agg(pi, agg_info, tc, rm_vsi_info);
2638 if (status)
2639 goto exit_rm_agg_cfg_tc;
2640
2641 /* Delete aggregator node(s) */
2642 status = ice_sched_rm_agg_cfg(pi, agg_info->agg_id, tc);
2643 if (status)
2644 goto exit_rm_agg_cfg_tc;
2645
2646 ice_clear_bit(tc, agg_info->tc_bitmap);
2647 exit_rm_agg_cfg_tc:
2648 return status;
2649 }
2650
2651 /**
2652 * ice_save_agg_tc_bitmap - save aggregator TC bitmap
2653 * @pi: port information structure
2654 * @agg_id: aggregator ID
2655 * @tc_bitmap: 8 bits TC bitmap
2656 *
2657 * Save aggregator TC bitmap. This function needs to be called with scheduler
2658 * lock held.
2659 */
2660 static enum ice_status
2661 ice_save_agg_tc_bitmap(struct ice_port_info *pi, u32 agg_id,
2662 ice_bitmap_t *tc_bitmap)
2663 {
2664 struct ice_sched_agg_info *agg_info;
2665
2666 agg_info = ice_get_agg_info(pi->hw, agg_id);
2667 if (!agg_info)
2668 return ICE_ERR_PARAM;
2669 ice_cp_bitmap(agg_info->replay_tc_bitmap, tc_bitmap,
2670 ICE_MAX_TRAFFIC_CLASS);
2671 return ICE_SUCCESS;
2672 }
2673
2674 /**
2675 * ice_sched_add_agg_cfg - create an aggregator node
2676 * @pi: port information structure
2677 * @agg_id: aggregator ID
2678 * @tc: TC number
2679 *
2680 * This function creates an aggregator node and intermediate nodes if required
2681 * for the given TC
2682 */
2683 static enum ice_status
2684 ice_sched_add_agg_cfg(struct ice_port_info *pi, u32 agg_id, u8 tc)
2685 {
2686 struct ice_sched_node *parent, *agg_node, *tc_node;
2687 u16 num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
2688 enum ice_status status = ICE_SUCCESS;
2689 struct ice_hw *hw = pi->hw;
2690 u32 first_node_teid;
2691 u16 num_nodes_added;
2692 u8 i, aggl;
2693
2694 tc_node = ice_sched_get_tc_node(pi, tc);
2695 if (!tc_node)
2696 return ICE_ERR_CFG;
2697
2698 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
2699 /* Does Agg node already exist ? */
2700 if (agg_node)
2701 return status;
2702
2703 aggl = ice_sched_get_agg_layer(hw);
2704
2705 /* need one node in Agg layer */
2706 num_nodes[aggl] = 1;
2707
2708 /* Check whether the intermediate nodes have space to add the
2709 * new aggregator. If they are full, then SW needs to allocate a new
2710 * intermediate node on those layers
2711 */
2712 for (i = hw->sw_entry_point_layer; i < aggl; i++) {
2713 parent = ice_sched_get_first_node(pi, tc_node, i);
2714
2715 /* scan all the siblings */
2716 while (parent) {
2717 if (parent->num_children < hw->max_children[i])
2718 break;
2719 parent = parent->sibling;
2720 }
2721
2722 /* all the nodes are full, reserve one for this layer */
2723 if (!parent)
2724 num_nodes[i]++;
2725 }
2726
2727 /* add the aggregator node */
2728 parent = tc_node;
2729 for (i = hw->sw_entry_point_layer; i <= aggl; i++) {
2730 if (!parent)
2731 return ICE_ERR_CFG;
2732
2733 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent, i,
2734 num_nodes[i],
2735 &first_node_teid,
2736 &num_nodes_added);
2737 if (status != ICE_SUCCESS || num_nodes[i] != num_nodes_added)
2738 return ICE_ERR_CFG;
2739
2740 /* The newly added node can be a new parent for the next
2741 * layer nodes
2742 */
2743 if (num_nodes_added) {
2744 parent = ice_sched_find_node_by_teid(tc_node,
2745 first_node_teid);
2746 /* register aggregator ID with the aggregator node */
2747 if (parent && i == aggl)
2748 parent->agg_id = agg_id;
2749 } else {
2750 parent = parent->children[0];
2751 }
2752 }
2753
2754 return ICE_SUCCESS;
2755 }
2756
2757 /**
2758 * ice_sched_cfg_agg - configure aggregator node
2759 * @pi: port information structure
2760 * @agg_id: aggregator ID
2761 * @agg_type: aggregator type queue, VSI, or aggregator group
2762 * @tc_bitmap: bits TC bitmap
2763 *
2764 * It registers a unique aggregator node into scheduler services. It
2765 * allows a user to register with a unique ID to track it's resources.
2766 * The aggregator type determines if this is a queue group, VSI group
2767 * or aggregator group. It then creates the aggregator node(s) for requested
2768 * TC(s) or removes an existing aggregator node including its configuration
2769 * if indicated via tc_bitmap. Call ice_rm_agg_cfg to release aggregator
2770 * resources and remove aggregator ID.
2771 * This function needs to be called with scheduler lock held.
2772 */
2773 static enum ice_status
2774 ice_sched_cfg_agg(struct ice_port_info *pi, u32 agg_id,
2775 enum ice_agg_type agg_type, ice_bitmap_t *tc_bitmap)
2776 {
2777 struct ice_sched_agg_info *agg_info;
2778 enum ice_status status = ICE_SUCCESS;
2779 struct ice_hw *hw = pi->hw;
2780 u8 tc;
2781
2782 agg_info = ice_get_agg_info(hw, agg_id);
2783 if (!agg_info) {
2784 /* Create new entry for new aggregator ID */
2785 agg_info = (struct ice_sched_agg_info *)
2786 ice_malloc(hw, sizeof(*agg_info));
2787 if (!agg_info)
2788 return ICE_ERR_NO_MEMORY;
2789
2790 agg_info->agg_id = agg_id;
2791 agg_info->agg_type = agg_type;
2792 agg_info->tc_bitmap[0] = 0;
2793
2794 /* Initialize the aggregator VSI list head */
2795 INIT_LIST_HEAD(&agg_info->agg_vsi_list);
2796
2797 /* Add new entry in aggregator list */
2798 LIST_ADD(&agg_info->list_entry, &hw->agg_list);
2799 }
2800 /* Create aggregator node(s) for requested TC(s) */
2801 ice_for_each_traffic_class(tc) {
2802 if (!ice_is_tc_ena(*tc_bitmap, tc)) {
2803 /* Delete aggregator cfg TC if it exists previously */
2804 status = ice_rm_agg_cfg_tc(pi, agg_info, tc, false);
2805 if (status)
2806 break;
2807 continue;
2808 }
2809
2810 /* Check if aggregator node for TC already exists */
2811 if (ice_is_tc_ena(agg_info->tc_bitmap[0], tc))
2812 continue;
2813
2814 /* Create new aggregator node for TC */
2815 status = ice_sched_add_agg_cfg(pi, agg_id, tc);
2816 if (status)
2817 break;
2818
2819 /* Save aggregator node's TC information */
2820 ice_set_bit(tc, agg_info->tc_bitmap);
2821 }
2822
2823 return status;
2824 }
2825
2826 /**
2827 * ice_cfg_agg - config aggregator node
2828 * @pi: port information structure
2829 * @agg_id: aggregator ID
2830 * @agg_type: aggregator type queue, VSI, or aggregator group
2831 * @tc_bitmap: bits TC bitmap
2832 *
2833 * This function configures aggregator node(s).
2834 */
2835 enum ice_status
2836 ice_cfg_agg(struct ice_port_info *pi, u32 agg_id, enum ice_agg_type agg_type,
2837 u8 tc_bitmap)
2838 {
2839 ice_bitmap_t bitmap = tc_bitmap;
2840 enum ice_status status;
2841
2842 ice_acquire_lock(&pi->sched_lock);
2843 status = ice_sched_cfg_agg(pi, agg_id, agg_type,
2844 (ice_bitmap_t *)&bitmap);
2845 if (!status)
2846 status = ice_save_agg_tc_bitmap(pi, agg_id,
2847 (ice_bitmap_t *)&bitmap);
2848 ice_release_lock(&pi->sched_lock);
2849 return status;
2850 }
2851
2852 /**
2853 * ice_get_agg_vsi_info - get the aggregator ID
2854 * @agg_info: aggregator info
2855 * @vsi_handle: software VSI handle
2856 *
2857 * The function returns aggregator VSI info based on VSI handle. This function
2858 * needs to be called with scheduler lock held.
2859 */
2860 static struct ice_sched_agg_vsi_info *
2861 ice_get_agg_vsi_info(struct ice_sched_agg_info *agg_info, u16 vsi_handle)
2862 {
2863 struct ice_sched_agg_vsi_info *agg_vsi_info;
2864
2865 LIST_FOR_EACH_ENTRY(agg_vsi_info, &agg_info->agg_vsi_list,
2866 ice_sched_agg_vsi_info, list_entry)
2867 if (agg_vsi_info->vsi_handle == vsi_handle)
2868 return agg_vsi_info;
2869
2870 return NULL;
2871 }
2872
2873 /**
2874 * ice_get_vsi_agg_info - get the aggregator info of VSI
2875 * @hw: pointer to the hardware structure
2876 * @vsi_handle: Sw VSI handle
2877 *
2878 * The function returns aggregator info of VSI represented via vsi_handle. The
2879 * VSI has in this case a different aggregator than the default one. This
2880 * function needs to be called with scheduler lock held.
2881 */
2882 static struct ice_sched_agg_info *
2883 ice_get_vsi_agg_info(struct ice_hw *hw, u16 vsi_handle)
2884 {
2885 struct ice_sched_agg_info *agg_info;
2886
2887 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
2888 list_entry) {
2889 struct ice_sched_agg_vsi_info *agg_vsi_info;
2890
2891 agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
2892 if (agg_vsi_info)
2893 return agg_info;
2894 }
2895 return NULL;
2896 }
2897
2898 /**
2899 * ice_save_agg_vsi_tc_bitmap - save aggregator VSI TC bitmap
2900 * @pi: port information structure
2901 * @agg_id: aggregator ID
2902 * @vsi_handle: software VSI handle
2903 * @tc_bitmap: TC bitmap of enabled TC(s)
2904 *
2905 * Save VSI to aggregator TC bitmap. This function needs to call with scheduler
2906 * lock held.
2907 */
2908 static enum ice_status
2909 ice_save_agg_vsi_tc_bitmap(struct ice_port_info *pi, u32 agg_id, u16 vsi_handle,
2910 ice_bitmap_t *tc_bitmap)
2911 {
2912 struct ice_sched_agg_vsi_info *agg_vsi_info;
2913 struct ice_sched_agg_info *agg_info;
2914
2915 agg_info = ice_get_agg_info(pi->hw, agg_id);
2916 if (!agg_info)
2917 return ICE_ERR_PARAM;
2918 /* check if entry already exist */
2919 agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
2920 if (!agg_vsi_info)
2921 return ICE_ERR_PARAM;
2922 ice_cp_bitmap(agg_vsi_info->replay_tc_bitmap, tc_bitmap,
2923 ICE_MAX_TRAFFIC_CLASS);
2924 return ICE_SUCCESS;
2925 }
2926
2927 /**
2928 * ice_sched_assoc_vsi_to_agg - associate/move VSI to new/default aggregator
2929 * @pi: port information structure
2930 * @agg_id: aggregator ID
2931 * @vsi_handle: software VSI handle
2932 * @tc_bitmap: TC bitmap of enabled TC(s)
2933 *
2934 * This function moves VSI to a new or default aggregator node. If VSI is
2935 * already associated to the aggregator node then no operation is performed on
2936 * the tree. This function needs to be called with scheduler lock held.
2937 */
2938 static enum ice_status
2939 ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
2940 u16 vsi_handle, ice_bitmap_t *tc_bitmap)
2941 {
2942 struct ice_sched_agg_vsi_info *agg_vsi_info, *old_agg_vsi_info = NULL;
2943 struct ice_sched_agg_info *agg_info, *old_agg_info;
2944 enum ice_status status = ICE_SUCCESS;
2945 struct ice_hw *hw = pi->hw;
2946 u8 tc;
2947
2948 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
2949 return ICE_ERR_PARAM;
2950 agg_info = ice_get_agg_info(hw, agg_id);
2951 if (!agg_info)
2952 return ICE_ERR_PARAM;
2953 /* If the vsi is already part of another aggregator then update
2954 * its vsi info list
2955 */
2956 old_agg_info = ice_get_vsi_agg_info(hw, vsi_handle);
2957 if (old_agg_info && old_agg_info != agg_info) {
2958 struct ice_sched_agg_vsi_info *vtmp;
2959
2960 LIST_FOR_EACH_ENTRY_SAFE(old_agg_vsi_info, vtmp,
2961 &old_agg_info->agg_vsi_list,
2962 ice_sched_agg_vsi_info, list_entry)
2963 if (old_agg_vsi_info->vsi_handle == vsi_handle)
2964 break;
2965 }
2966
2967 /* check if entry already exist */
2968 agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
2969 if (!agg_vsi_info) {
2970 /* Create new entry for VSI under aggregator list */
2971 agg_vsi_info = (struct ice_sched_agg_vsi_info *)
2972 ice_malloc(hw, sizeof(*agg_vsi_info));
2973 if (!agg_vsi_info)
2974 return ICE_ERR_PARAM;
2975
2976 /* add VSI ID into the aggregator list */
2977 agg_vsi_info->vsi_handle = vsi_handle;
2978 LIST_ADD(&agg_vsi_info->list_entry, &agg_info->agg_vsi_list);
2979 }
2980 /* Move VSI node to new aggregator node for requested TC(s) */
2981 ice_for_each_traffic_class(tc) {
2982 if (!ice_is_tc_ena(*tc_bitmap, tc))
2983 continue;
2984
2985 /* Move VSI to new aggregator */
2986 status = ice_sched_move_vsi_to_agg(pi, vsi_handle, agg_id, tc);
2987 if (status)
2988 break;
2989
2990 ice_set_bit(tc, agg_vsi_info->tc_bitmap);
2991 if (old_agg_vsi_info)
2992 ice_clear_bit(tc, old_agg_vsi_info->tc_bitmap);
2993 }
2994 if (old_agg_vsi_info && !old_agg_vsi_info->tc_bitmap[0]) {
2995 LIST_DEL(&old_agg_vsi_info->list_entry);
2996 ice_free(pi->hw, old_agg_vsi_info);
2997 }
2998 return status;
2999 }
3000
3001 /**
3002 * ice_sched_rm_unused_rl_prof - remove unused RL profile
3003 * @hw: pointer to the hardware structure
3004 *
3005 * This function removes unused rate limit profiles from the HW and
3006 * SW DB. The caller needs to hold scheduler lock.
3007 */
3008 static void ice_sched_rm_unused_rl_prof(struct ice_hw *hw)
3009 {
3010 u16 ln;
3011
3012 for (ln = 0; ln < hw->num_tx_sched_layers; ln++) {
3013 struct ice_aqc_rl_profile_info *rl_prof_elem;
3014 struct ice_aqc_rl_profile_info *rl_prof_tmp;
3015
3016 LIST_FOR_EACH_ENTRY_SAFE(rl_prof_elem, rl_prof_tmp,
3017 &hw->rl_prof_list[ln],
3018 ice_aqc_rl_profile_info, list_entry) {
3019 if (!ice_sched_del_rl_profile(hw, rl_prof_elem))
3020 ice_debug(hw, ICE_DBG_SCHED, "Removed rl profile\n");
3021 }
3022 }
3023 }
3024
3025 /**
3026 * ice_sched_update_elem - update element
3027 * @hw: pointer to the HW struct
3028 * @node: pointer to node
3029 * @info: node info to update
3030 *
3031 * Update the HW DB, and local SW DB of node. Update the scheduling
3032 * parameters of node from argument info data buffer (Info->data buf) and
3033 * returns success or error on config sched element failure. The caller
3034 * needs to hold scheduler lock.
3035 */
3036 static enum ice_status
3037 ice_sched_update_elem(struct ice_hw *hw, struct ice_sched_node *node,
3038 struct ice_aqc_txsched_elem_data *info)
3039 {
3040 struct ice_aqc_txsched_elem_data buf;
3041 enum ice_status status;
3042 u16 elem_cfgd = 0;
3043 u16 num_elems = 1;
3044
3045 buf = *info;
3046 /* For TC nodes, CIR config is not supported */
3047 if (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_TC)
3048 buf.data.valid_sections &= ~ICE_AQC_ELEM_VALID_CIR;
3049 /* Parent TEID is reserved field in this aq call */
3050 buf.parent_teid = 0;
3051 /* Element type is reserved field in this aq call */
3052 buf.data.elem_type = 0;
3053 /* Flags is reserved field in this aq call */
3054 buf.data.flags = 0;
3055
3056 /* Update HW DB */
3057 /* Configure element node */
3058 status = ice_aq_cfg_sched_elems(hw, num_elems, &buf, sizeof(buf),
3059 &elem_cfgd, NULL);
3060 if (status || elem_cfgd != num_elems) {
3061 ice_debug(hw, ICE_DBG_SCHED, "Config sched elem error\n");
3062 return ICE_ERR_CFG;
3063 }
3064
3065 /* Config success case */
3066 /* Now update local SW DB */
3067 /* Only copy the data portion of info buffer */
3068 node->info.data = info->data;
3069 return status;
3070 }
3071
3072 /**
3073 * ice_sched_cfg_node_bw_alloc - configure node BW weight/alloc params
3074 * @hw: pointer to the HW struct
3075 * @node: sched node to configure
3076 * @rl_type: rate limit type CIR, EIR, or shared
3077 * @bw_alloc: BW weight/allocation
3078 *
3079 * This function configures node element's BW allocation.
3080 */
3081 static enum ice_status
3082 ice_sched_cfg_node_bw_alloc(struct ice_hw *hw, struct ice_sched_node *node,
3083 enum ice_rl_type rl_type, u16 bw_alloc)
3084 {
3085 struct ice_aqc_txsched_elem_data buf;
3086 struct ice_aqc_txsched_elem *data;
3087 enum ice_status status;
3088
3089 buf = node->info;
3090 data = &buf.data;
3091 if (rl_type == ICE_MIN_BW) {
3092 data->valid_sections |= ICE_AQC_ELEM_VALID_CIR;
3093 data->cir_bw.bw_alloc = CPU_TO_LE16(bw_alloc);
3094 } else if (rl_type == ICE_MAX_BW) {
3095 data->valid_sections |= ICE_AQC_ELEM_VALID_EIR;
3096 data->eir_bw.bw_alloc = CPU_TO_LE16(bw_alloc);
3097 } else {
3098 return ICE_ERR_PARAM;
3099 }
3100
3101 /* Configure element */
3102 status = ice_sched_update_elem(hw, node, &buf);
3103 return status;
3104 }
3105
3106 /**
3107 * ice_move_vsi_to_agg - moves VSI to new or default aggregator
3108 * @pi: port information structure
3109 * @agg_id: aggregator ID
3110 * @vsi_handle: software VSI handle
3111 * @tc_bitmap: TC bitmap of enabled TC(s)
3112 *
3113 * Move or associate VSI to a new or default aggregator node.
3114 */
3115 enum ice_status
3116 ice_move_vsi_to_agg(struct ice_port_info *pi, u32 agg_id, u16 vsi_handle,
3117 u8 tc_bitmap)
3118 {
3119 ice_bitmap_t bitmap = tc_bitmap;
3120 enum ice_status status;
3121
3122 ice_acquire_lock(&pi->sched_lock);
3123 status = ice_sched_assoc_vsi_to_agg(pi, agg_id, vsi_handle,
3124 (ice_bitmap_t *)&bitmap);
3125 if (!status)
3126 status = ice_save_agg_vsi_tc_bitmap(pi, agg_id, vsi_handle,
3127 (ice_bitmap_t *)&bitmap);
3128 ice_release_lock(&pi->sched_lock);
3129 return status;
3130 }
3131
3132 /**
3133 * ice_rm_agg_cfg - remove aggregator configuration
3134 * @pi: port information structure
3135 * @agg_id: aggregator ID
3136 *
3137 * This function removes aggregator reference to VSI and delete aggregator ID
3138 * info. It removes the aggregator configuration completely.
3139 */
3140 enum ice_status ice_rm_agg_cfg(struct ice_port_info *pi, u32 agg_id)
3141 {
3142 struct ice_sched_agg_info *agg_info;
3143 enum ice_status status = ICE_SUCCESS;
3144 u8 tc;
3145
3146 ice_acquire_lock(&pi->sched_lock);
3147 agg_info = ice_get_agg_info(pi->hw, agg_id);
3148 if (!agg_info) {
3149 status = ICE_ERR_DOES_NOT_EXIST;
3150 goto exit_ice_rm_agg_cfg;
3151 }
3152
3153 ice_for_each_traffic_class(tc) {
3154 status = ice_rm_agg_cfg_tc(pi, agg_info, tc, true);
3155 if (status)
3156 goto exit_ice_rm_agg_cfg;
3157 }
3158
3159 if (ice_is_any_bit_set(agg_info->tc_bitmap, ICE_MAX_TRAFFIC_CLASS)) {
3160 status = ICE_ERR_IN_USE;
3161 goto exit_ice_rm_agg_cfg;
3162 }
3163
3164 /* Safe to delete entry now */
3165 LIST_DEL(&agg_info->list_entry);
3166 ice_free(pi->hw, agg_info);
3167
3168 /* Remove unused RL profile IDs from HW and SW DB */
3169 ice_sched_rm_unused_rl_prof(pi->hw);
3170
3171 exit_ice_rm_agg_cfg:
3172 ice_release_lock(&pi->sched_lock);
3173 return status;
3174 }
3175
3176 /**
3177 * ice_set_clear_cir_bw_alloc - set or clear CIR BW alloc information
3178 * @bw_t_info: bandwidth type information structure
3179 * @bw_alloc: Bandwidth allocation information
3180 *
3181 * Save or clear CIR BW alloc information (bw_alloc) in the passed param
3182 * bw_t_info.
3183 */
3184 static void
3185 ice_set_clear_cir_bw_alloc(struct ice_bw_type_info *bw_t_info, u16 bw_alloc)
3186 {
3187 bw_t_info->cir_bw.bw_alloc = bw_alloc;
3188 if (bw_t_info->cir_bw.bw_alloc)
3189 ice_set_bit(ICE_BW_TYPE_CIR_WT, bw_t_info->bw_t_bitmap);
3190 else
3191 ice_clear_bit(ICE_BW_TYPE_CIR_WT, bw_t_info->bw_t_bitmap);
3192 }
3193
3194 /**
3195 * ice_set_clear_eir_bw_alloc - set or clear EIR BW alloc information
3196 * @bw_t_info: bandwidth type information structure
3197 * @bw_alloc: Bandwidth allocation information
3198 *
3199 * Save or clear EIR BW alloc information (bw_alloc) in the passed param
3200 * bw_t_info.
3201 */
3202 static void
3203 ice_set_clear_eir_bw_alloc(struct ice_bw_type_info *bw_t_info, u16 bw_alloc)
3204 {
3205 bw_t_info->eir_bw.bw_alloc = bw_alloc;
3206 if (bw_t_info->eir_bw.bw_alloc)
3207 ice_set_bit(ICE_BW_TYPE_EIR_WT, bw_t_info->bw_t_bitmap);
3208 else
3209 ice_clear_bit(ICE_BW_TYPE_EIR_WT, bw_t_info->bw_t_bitmap);
3210 }
3211
3212 /**
3213 * ice_sched_save_vsi_bw_alloc - save VSI node's BW alloc information
3214 * @pi: port information structure
3215 * @vsi_handle: sw VSI handle
3216 * @tc: traffic class
3217 * @rl_type: rate limit type min or max
3218 * @bw_alloc: Bandwidth allocation information
3219 *
3220 * Save BW alloc information of VSI type node for post replay use.
3221 */
3222 static enum ice_status
3223 ice_sched_save_vsi_bw_alloc(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
3224 enum ice_rl_type rl_type, u16 bw_alloc)
3225 {
3226 struct ice_vsi_ctx *vsi_ctx;
3227
3228 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
3229 return ICE_ERR_PARAM;
3230 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
3231 if (!vsi_ctx)
3232 return ICE_ERR_PARAM;
3233 switch (rl_type) {
3234 case ICE_MIN_BW:
3235 ice_set_clear_cir_bw_alloc(&vsi_ctx->sched.bw_t_info[tc],
3236 bw_alloc);
3237 break;
3238 case ICE_MAX_BW:
3239 ice_set_clear_eir_bw_alloc(&vsi_ctx->sched.bw_t_info[tc],
3240 bw_alloc);
3241 break;
3242 default:
3243 return ICE_ERR_PARAM;
3244 }
3245 return ICE_SUCCESS;
3246 }
3247
3248 /**
3249 * ice_set_clear_cir_bw - set or clear CIR BW
3250 * @bw_t_info: bandwidth type information structure
3251 * @bw: bandwidth in Kbps - Kilo bits per sec
3252 *
3253 * Save or clear CIR bandwidth (BW) in the passed param bw_t_info.
3254 */
3255 static void ice_set_clear_cir_bw(struct ice_bw_type_info *bw_t_info, u32 bw)
3256 {
3257 if (bw == ICE_SCHED_DFLT_BW) {
3258 ice_clear_bit(ICE_BW_TYPE_CIR, bw_t_info->bw_t_bitmap);
3259 bw_t_info->cir_bw.bw = 0;
3260 } else {
3261 /* Save type of BW information */
3262 ice_set_bit(ICE_BW_TYPE_CIR, bw_t_info->bw_t_bitmap);
3263 bw_t_info->cir_bw.bw = bw;
3264 }
3265 }
3266
3267 /**
3268 * ice_set_clear_eir_bw - set or clear EIR BW
3269 * @bw_t_info: bandwidth type information structure
3270 * @bw: bandwidth in Kbps - Kilo bits per sec
3271 *
3272 * Save or clear EIR bandwidth (BW) in the passed param bw_t_info.
3273 */
3274 static void ice_set_clear_eir_bw(struct ice_bw_type_info *bw_t_info, u32 bw)
3275 {
3276 if (bw == ICE_SCHED_DFLT_BW) {
3277 ice_clear_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap);
3278 bw_t_info->eir_bw.bw = 0;
3279 } else {
3280 /* save EIR BW information */
3281 ice_set_bit(ICE_BW_TYPE_EIR, bw_t_info->bw_t_bitmap);
3282 bw_t_info->eir_bw.bw = bw;
3283 }
3284 }
3285
3286 /**
3287 * ice_set_clear_shared_bw - set or clear shared BW
3288 * @bw_t_info: bandwidth type information structure
3289 * @bw: bandwidth in Kbps - Kilo bits per sec
3290 *
3291 * Save or clear shared bandwidth (BW) in the passed param bw_t_info.
3292 */
3293 static void ice_set_clear_shared_bw(struct ice_bw_type_info *bw_t_info, u32 bw)
3294 {
3295 if (bw == ICE_SCHED_DFLT_BW) {
3296 ice_clear_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap);
3297 bw_t_info->shared_bw = 0;
3298 } else {
3299 /* save shared BW information */
3300 ice_set_bit(ICE_BW_TYPE_SHARED, bw_t_info->bw_t_bitmap);
3301 bw_t_info->shared_bw = bw;
3302 }
3303 }
3304
3305 /**
3306 * ice_sched_save_vsi_bw - save VSI node's BW information
3307 * @pi: port information structure
3308 * @vsi_handle: sw VSI handle
3309 * @tc: traffic class
3310 * @rl_type: rate limit type min, max, or shared
3311 * @bw: bandwidth in Kbps - Kilo bits per sec
3312 *
3313 * Save BW information of VSI type node for post replay use.
3314 */
3315 static enum ice_status
3316 ice_sched_save_vsi_bw(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
3317 enum ice_rl_type rl_type, u32 bw)
3318 {
3319 struct ice_vsi_ctx *vsi_ctx;
3320
3321 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
3322 return ICE_ERR_PARAM;
3323 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
3324 if (!vsi_ctx)
3325 return ICE_ERR_PARAM;
3326 switch (rl_type) {
3327 case ICE_MIN_BW:
3328 ice_set_clear_cir_bw(&vsi_ctx->sched.bw_t_info[tc], bw);
3329 break;
3330 case ICE_MAX_BW:
3331 ice_set_clear_eir_bw(&vsi_ctx->sched.bw_t_info[tc], bw);
3332 break;
3333 case ICE_SHARED_BW:
3334 ice_set_clear_shared_bw(&vsi_ctx->sched.bw_t_info[tc], bw);
3335 break;
3336 default:
3337 return ICE_ERR_PARAM;
3338 }
3339 return ICE_SUCCESS;
3340 }
3341
3342 /**
3343 * ice_set_clear_prio - set or clear priority information
3344 * @bw_t_info: bandwidth type information structure
3345 * @prio: priority to save
3346 *
3347 * Save or clear priority (prio) in the passed param bw_t_info.
3348 */
3349 static void ice_set_clear_prio(struct ice_bw_type_info *bw_t_info, u8 prio)
3350 {
3351 bw_t_info->generic = prio;
3352 if (bw_t_info->generic)
3353 ice_set_bit(ICE_BW_TYPE_PRIO, bw_t_info->bw_t_bitmap);
3354 else
3355 ice_clear_bit(ICE_BW_TYPE_PRIO, bw_t_info->bw_t_bitmap);
3356 }
3357
3358 /**
3359 * ice_sched_save_vsi_prio - save VSI node's priority information
3360 * @pi: port information structure
3361 * @vsi_handle: Software VSI handle
3362 * @tc: traffic class
3363 * @prio: priority to save
3364 *
3365 * Save priority information of VSI type node for post replay use.
3366 */
3367 static enum ice_status
3368 ice_sched_save_vsi_prio(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
3369 u8 prio)
3370 {
3371 struct ice_vsi_ctx *vsi_ctx;
3372
3373 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
3374 return ICE_ERR_PARAM;
3375 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
3376 if (!vsi_ctx)
3377 return ICE_ERR_PARAM;
3378 if (tc >= ICE_MAX_TRAFFIC_CLASS)
3379 return ICE_ERR_PARAM;
3380 ice_set_clear_prio(&vsi_ctx->sched.bw_t_info[tc], prio);
3381 return ICE_SUCCESS;
3382 }
3383
3384 /**
3385 * ice_sched_save_agg_bw_alloc - save aggregator node's BW alloc information
3386 * @pi: port information structure
3387 * @agg_id: node aggregator ID
3388 * @tc: traffic class
3389 * @rl_type: rate limit type min or max
3390 * @bw_alloc: bandwidth alloc information
3391 *
3392 * Save BW alloc information of AGG type node for post replay use.
3393 */
3394 static enum ice_status
3395 ice_sched_save_agg_bw_alloc(struct ice_port_info *pi, u32 agg_id, u8 tc,
3396 enum ice_rl_type rl_type, u16 bw_alloc)
3397 {
3398 struct ice_sched_agg_info *agg_info;
3399
3400 agg_info = ice_get_agg_info(pi->hw, agg_id);
3401 if (!agg_info)
3402 return ICE_ERR_PARAM;
3403 if (!ice_is_tc_ena(agg_info->tc_bitmap[0], tc))
3404 return ICE_ERR_PARAM;
3405 switch (rl_type) {
3406 case ICE_MIN_BW:
3407 ice_set_clear_cir_bw_alloc(&agg_info->bw_t_info[tc], bw_alloc);
3408 break;
3409 case ICE_MAX_BW:
3410 ice_set_clear_eir_bw_alloc(&agg_info->bw_t_info[tc], bw_alloc);
3411 break;
3412 default:
3413 return ICE_ERR_PARAM;
3414 }
3415 return ICE_SUCCESS;
3416 }
3417
3418 /**
3419 * ice_sched_save_agg_bw - save aggregator node's BW information
3420 * @pi: port information structure
3421 * @agg_id: node aggregator ID
3422 * @tc: traffic class
3423 * @rl_type: rate limit type min, max, or shared
3424 * @bw: bandwidth in Kbps - Kilo bits per sec
3425 *
3426 * Save BW information of AGG type node for post replay use.
3427 */
3428 static enum ice_status
3429 ice_sched_save_agg_bw(struct ice_port_info *pi, u32 agg_id, u8 tc,
3430 enum ice_rl_type rl_type, u32 bw)
3431 {
3432 struct ice_sched_agg_info *agg_info;
3433
3434 agg_info = ice_get_agg_info(pi->hw, agg_id);
3435 if (!agg_info)
3436 return ICE_ERR_PARAM;
3437 if (!ice_is_tc_ena(agg_info->tc_bitmap[0], tc))
3438 return ICE_ERR_PARAM;
3439 switch (rl_type) {
3440 case ICE_MIN_BW:
3441 ice_set_clear_cir_bw(&agg_info->bw_t_info[tc], bw);
3442 break;
3443 case ICE_MAX_BW:
3444 ice_set_clear_eir_bw(&agg_info->bw_t_info[tc], bw);
3445 break;
3446 case ICE_SHARED_BW:
3447 ice_set_clear_shared_bw(&agg_info->bw_t_info[tc], bw);
3448 break;
3449 default:
3450 return ICE_ERR_PARAM;
3451 }
3452 return ICE_SUCCESS;
3453 }
3454
3455 /**
3456 * ice_cfg_vsi_bw_lmt_per_tc - configure VSI BW limit per TC
3457 * @pi: port information structure
3458 * @vsi_handle: software VSI handle
3459 * @tc: traffic class
3460 * @rl_type: min or max
3461 * @bw: bandwidth in Kbps
3462 *
3463 * This function configures BW limit of VSI scheduling node based on TC
3464 * information.
3465 */
3466 enum ice_status
3467 ice_cfg_vsi_bw_lmt_per_tc(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
3468 enum ice_rl_type rl_type, u32 bw)
3469 {
3470 enum ice_status status;
3471
3472 status = ice_sched_set_node_bw_lmt_per_tc(pi, vsi_handle,
3473 ICE_AGG_TYPE_VSI,
3474 tc, rl_type, bw);
3475 if (!status) {
3476 ice_acquire_lock(&pi->sched_lock);
3477 status = ice_sched_save_vsi_bw(pi, vsi_handle, tc, rl_type, bw);
3478 ice_release_lock(&pi->sched_lock);
3479 }
3480 return status;
3481 }
3482
3483 /**
3484 * ice_cfg_vsi_bw_dflt_lmt_per_tc - configure default VSI BW limit per TC
3485 * @pi: port information structure
3486 * @vsi_handle: software VSI handle
3487 * @tc: traffic class
3488 * @rl_type: min or max
3489 *
3490 * This function configures default BW limit of VSI scheduling node based on TC
3491 * information.
3492 */
3493 enum ice_status
3494 ice_cfg_vsi_bw_dflt_lmt_per_tc(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
3495 enum ice_rl_type rl_type)
3496 {
3497 enum ice_status status;
3498
3499 status = ice_sched_set_node_bw_lmt_per_tc(pi, vsi_handle,
3500 ICE_AGG_TYPE_VSI,
3501 tc, rl_type,
3502 ICE_SCHED_DFLT_BW);
3503 if (!status) {
3504 ice_acquire_lock(&pi->sched_lock);
3505 status = ice_sched_save_vsi_bw(pi, vsi_handle, tc, rl_type,
3506 ICE_SCHED_DFLT_BW);
3507 ice_release_lock(&pi->sched_lock);
3508 }
3509 return status;
3510 }
3511
3512 /**
3513 * ice_cfg_agg_bw_lmt_per_tc - configure aggregator BW limit per TC
3514 * @pi: port information structure
3515 * @agg_id: aggregator ID
3516 * @tc: traffic class
3517 * @rl_type: min or max
3518 * @bw: bandwidth in Kbps
3519 *
3520 * This function applies BW limit to aggregator scheduling node based on TC
3521 * information.
3522 */
3523 enum ice_status
3524 ice_cfg_agg_bw_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc,
3525 enum ice_rl_type rl_type, u32 bw)
3526 {
3527 enum ice_status status;
3528
3529 status = ice_sched_set_node_bw_lmt_per_tc(pi, agg_id, ICE_AGG_TYPE_AGG,
3530 tc, rl_type, bw);
3531 if (!status) {
3532 ice_acquire_lock(&pi->sched_lock);
3533 status = ice_sched_save_agg_bw(pi, agg_id, tc, rl_type, bw);
3534 ice_release_lock(&pi->sched_lock);
3535 }
3536 return status;
3537 }
3538
3539 /**
3540 * ice_cfg_agg_bw_dflt_lmt_per_tc - configure aggregator BW default limit per TC
3541 * @pi: port information structure
3542 * @agg_id: aggregator ID
3543 * @tc: traffic class
3544 * @rl_type: min or max
3545 *
3546 * This function applies default BW limit to aggregator scheduling node based
3547 * on TC information.
3548 */
3549 enum ice_status
3550 ice_cfg_agg_bw_dflt_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc,
3551 enum ice_rl_type rl_type)
3552 {
3553 enum ice_status status;
3554
3555 status = ice_sched_set_node_bw_lmt_per_tc(pi, agg_id, ICE_AGG_TYPE_AGG,
3556 tc, rl_type,
3557 ICE_SCHED_DFLT_BW);
3558 if (!status) {
3559 ice_acquire_lock(&pi->sched_lock);
3560 status = ice_sched_save_agg_bw(pi, agg_id, tc, rl_type,
3561 ICE_SCHED_DFLT_BW);
3562 ice_release_lock(&pi->sched_lock);
3563 }
3564 return status;
3565 }
3566
3567 /**
3568 * ice_cfg_vsi_bw_shared_lmt - configure VSI BW shared limit
3569 * @pi: port information structure
3570 * @vsi_handle: software VSI handle
3571 * @min_bw: minimum bandwidth in Kbps
3572 * @max_bw: maximum bandwidth in Kbps
3573 * @shared_bw: shared bandwidth in Kbps
3574 *
3575 * Configure shared rate limiter(SRL) of all VSI type nodes across all traffic
3576 * classes for VSI matching handle.
3577 */
3578 enum ice_status
3579 ice_cfg_vsi_bw_shared_lmt(struct ice_port_info *pi, u16 vsi_handle, u32 min_bw,
3580 u32 max_bw, u32 shared_bw)
3581 {
3582 return ice_sched_set_vsi_bw_shared_lmt(pi, vsi_handle, min_bw, max_bw,
3583 shared_bw);
3584 }
3585
3586 /**
3587 * ice_cfg_vsi_bw_no_shared_lmt - configure VSI BW for no shared limiter
3588 * @pi: port information structure
3589 * @vsi_handle: software VSI handle
3590 *
3591 * This function removes the shared rate limiter(SRL) of all VSI type nodes
3592 * across all traffic classes for VSI matching handle.
3593 */
3594 enum ice_status
3595 ice_cfg_vsi_bw_no_shared_lmt(struct ice_port_info *pi, u16 vsi_handle)
3596 {
3597 return ice_sched_set_vsi_bw_shared_lmt(pi, vsi_handle,
3598 ICE_SCHED_DFLT_BW,
3599 ICE_SCHED_DFLT_BW,
3600 ICE_SCHED_DFLT_BW);
3601 }
3602
3603 /**
3604 * ice_cfg_agg_bw_shared_lmt - configure aggregator BW shared limit
3605 * @pi: port information structure
3606 * @agg_id: aggregator ID
3607 * @min_bw: minimum bandwidth in Kbps
3608 * @max_bw: maximum bandwidth in Kbps
3609 * @shared_bw: shared bandwidth in Kbps
3610 *
3611 * This function configures the shared rate limiter(SRL) of all aggregator type
3612 * nodes across all traffic classes for aggregator matching agg_id.
3613 */
3614 enum ice_status
3615 ice_cfg_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id, u32 min_bw,
3616 u32 max_bw, u32 shared_bw)
3617 {
3618 return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, min_bw, max_bw,
3619 shared_bw);
3620 }
3621
3622 /**
3623 * ice_cfg_agg_bw_no_shared_lmt - configure aggregator BW for no shared limiter
3624 * @pi: port information structure
3625 * @agg_id: aggregator ID
3626 *
3627 * This function removes the shared rate limiter(SRL) of all aggregator type
3628 * nodes across all traffic classes for aggregator matching agg_id.
3629 */
3630 enum ice_status
3631 ice_cfg_agg_bw_no_shared_lmt(struct ice_port_info *pi, u32 agg_id)
3632 {
3633 return ice_sched_set_agg_bw_shared_lmt(pi, agg_id, ICE_SCHED_DFLT_BW,
3634 ICE_SCHED_DFLT_BW,
3635 ICE_SCHED_DFLT_BW);
3636 }
3637
3638 /**
3639 * ice_cfg_agg_bw_shared_lmt_per_tc - config aggregator BW shared limit per tc
3640 * @pi: port information structure
3641 * @agg_id: aggregator ID
3642 * @tc: traffic class
3643 * @min_bw: minimum bandwidth in Kbps
3644 * @max_bw: maximum bandwidth in Kbps
3645 * @shared_bw: shared bandwidth in Kbps
3646 *
3647 * This function configures the shared rate limiter(SRL) of all aggregator type
3648 * nodes across all traffic classes for aggregator matching agg_id.
3649 */
3650 enum ice_status
3651 ice_cfg_agg_bw_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc,
3652 u32 min_bw, u32 max_bw, u32 shared_bw)
3653 {
3654 return ice_sched_set_agg_bw_shared_lmt_per_tc(pi, agg_id, tc, min_bw,
3655 max_bw, shared_bw);
3656 }
3657
3658 /**
3659 * ice_cfg_agg_bw_no_shared_lmt_per_tc - cfg aggregator BW shared limit per tc
3660 * @pi: port information structure
3661 * @agg_id: aggregator ID
3662 * @tc: traffic class
3663 *
3664 * This function configures the shared rate limiter(SRL) of all aggregator type
3665 * nodes across all traffic classes for aggregator matching agg_id.
3666 */
3667 enum ice_status
3668 ice_cfg_agg_bw_no_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id, u8 tc)
3669 {
3670 return ice_sched_set_agg_bw_shared_lmt_per_tc(pi, agg_id, tc,
3671 ICE_SCHED_DFLT_BW,
3672 ICE_SCHED_DFLT_BW,
3673 ICE_SCHED_DFLT_BW);
3674 }
3675
3676 /**
3677 * ice_cfg_vsi_q_priority - config VSI queue priority of node
3678 * @pi: port information structure
3679 * @num_qs: number of VSI queues
3680 * @q_ids: queue IDs array
3681 * @q_prio: queue priority array
3682 *
3683 * This function configures the queue node priority (Sibling Priority) of the
3684 * passed in VSI's queue(s) for a given traffic class (TC).
3685 */
3686 enum ice_status
3687 ice_cfg_vsi_q_priority(struct ice_port_info *pi, u16 num_qs, u32 *q_ids,
3688 u8 *q_prio)
3689 {
3690 enum ice_status status = ICE_ERR_PARAM;
3691 u16 i;
3692
3693 ice_acquire_lock(&pi->sched_lock);
3694
3695 for (i = 0; i < num_qs; i++) {
3696 struct ice_sched_node *node;
3697
3698 node = ice_sched_find_node_by_teid(pi->root, q_ids[i]);
3699 if (!node || node->info.data.elem_type !=
3700 ICE_AQC_ELEM_TYPE_LEAF) {
3701 status = ICE_ERR_PARAM;
3702 break;
3703 }
3704 /* Configure Priority */
3705 status = ice_sched_cfg_sibl_node_prio(pi, node, q_prio[i]);
3706 if (status)
3707 break;
3708 }
3709
3710 ice_release_lock(&pi->sched_lock);
3711 return status;
3712 }
3713
3714 /**
3715 * ice_cfg_agg_vsi_priority_per_tc - config aggregator's VSI priority per TC
3716 * @pi: port information structure
3717 * @agg_id: Aggregator ID
3718 * @num_vsis: number of VSI(s)
3719 * @vsi_handle_arr: array of software VSI handles
3720 * @node_prio: pointer to node priority
3721 * @tc: traffic class
3722 *
3723 * This function configures the node priority (Sibling Priority) of the
3724 * passed in VSI's for a given traffic class (TC) of an Aggregator ID.
3725 */
3726 enum ice_status
3727 ice_cfg_agg_vsi_priority_per_tc(struct ice_port_info *pi, u32 agg_id,
3728 u16 num_vsis, u16 *vsi_handle_arr,
3729 u8 *node_prio, u8 tc)
3730 {
3731 struct ice_sched_agg_vsi_info *agg_vsi_info;
3732 struct ice_sched_node *tc_node, *agg_node;
3733 enum ice_status status = ICE_ERR_PARAM;
3734 struct ice_sched_agg_info *agg_info;
3735 bool agg_id_present = false;
3736 struct ice_hw *hw = pi->hw;
3737 u16 i;
3738
3739 ice_acquire_lock(&pi->sched_lock);
3740 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
3741 list_entry)
3742 if (agg_info->agg_id == agg_id) {
3743 agg_id_present = true;
3744 break;
3745 }
3746 if (!agg_id_present)
3747 goto exit_agg_priority_per_tc;
3748
3749 tc_node = ice_sched_get_tc_node(pi, tc);
3750 if (!tc_node)
3751 goto exit_agg_priority_per_tc;
3752
3753 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
3754 if (!agg_node)
3755 goto exit_agg_priority_per_tc;
3756
3757 if (num_vsis > hw->max_children[agg_node->tx_sched_layer])
3758 goto exit_agg_priority_per_tc;
3759
3760 for (i = 0; i < num_vsis; i++) {
3761 struct ice_sched_node *vsi_node;
3762 bool vsi_handle_valid = false;
3763 u16 vsi_handle;
3764
3765 status = ICE_ERR_PARAM;
3766 vsi_handle = vsi_handle_arr[i];
3767 if (!ice_is_vsi_valid(hw, vsi_handle))
3768 goto exit_agg_priority_per_tc;
3769 /* Verify child nodes before applying settings */
3770 LIST_FOR_EACH_ENTRY(agg_vsi_info, &agg_info->agg_vsi_list,
3771 ice_sched_agg_vsi_info, list_entry)
3772 if (agg_vsi_info->vsi_handle == vsi_handle) {
3773 vsi_handle_valid = true;
3774 break;
3775 }
3776
3777 if (!vsi_handle_valid)
3778 goto exit_agg_priority_per_tc;
3779
3780 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
3781 if (!vsi_node)
3782 goto exit_agg_priority_per_tc;
3783
3784 if (ice_sched_find_node_in_subtree(hw, agg_node, vsi_node)) {
3785 /* Configure Priority */
3786 status = ice_sched_cfg_sibl_node_prio(pi, vsi_node,
3787 node_prio[i]);
3788 if (status)
3789 break;
3790 status = ice_sched_save_vsi_prio(pi, vsi_handle, tc,
3791 node_prio[i]);
3792 if (status)
3793 break;
3794 }
3795 }
3796
3797 exit_agg_priority_per_tc:
3798 ice_release_lock(&pi->sched_lock);
3799 return status;
3800 }
3801
3802 /**
3803 * ice_cfg_vsi_bw_alloc - config VSI BW alloc per TC
3804 * @pi: port information structure
3805 * @vsi_handle: software VSI handle
3806 * @ena_tcmap: enabled TC map
3807 * @rl_type: Rate limit type CIR/EIR
3808 * @bw_alloc: Array of BW alloc
3809 *
3810 * This function configures the BW allocation of the passed in VSI's
3811 * node(s) for enabled traffic class.
3812 */
3813 enum ice_status
3814 ice_cfg_vsi_bw_alloc(struct ice_port_info *pi, u16 vsi_handle, u8 ena_tcmap,
3815 enum ice_rl_type rl_type, u8 *bw_alloc)
3816 {
3817 enum ice_status status = ICE_SUCCESS;
3818 u8 tc;
3819
3820 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
3821 return ICE_ERR_PARAM;
3822
3823 ice_acquire_lock(&pi->sched_lock);
3824
3825 /* Return success if no nodes are present across TC */
3826 ice_for_each_traffic_class(tc) {
3827 struct ice_sched_node *tc_node, *vsi_node;
3828
3829 if (!ice_is_tc_ena(ena_tcmap, tc))
3830 continue;
3831
3832 tc_node = ice_sched_get_tc_node(pi, tc);
3833 if (!tc_node)
3834 continue;
3835
3836 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
3837 if (!vsi_node)
3838 continue;
3839
3840 status = ice_sched_cfg_node_bw_alloc(pi->hw, vsi_node, rl_type,
3841 bw_alloc[tc]);
3842 if (status)
3843 break;
3844 status = ice_sched_save_vsi_bw_alloc(pi, vsi_handle, tc,
3845 rl_type, bw_alloc[tc]);
3846 if (status)
3847 break;
3848 }
3849
3850 ice_release_lock(&pi->sched_lock);
3851 return status;
3852 }
3853
3854 /**
3855 * ice_cfg_agg_bw_alloc - config aggregator BW alloc
3856 * @pi: port information structure
3857 * @agg_id: aggregator ID
3858 * @ena_tcmap: enabled TC map
3859 * @rl_type: rate limit type CIR/EIR
3860 * @bw_alloc: array of BW alloc
3861 *
3862 * This function configures the BW allocation of passed in aggregator for
3863 * enabled traffic class(s).
3864 */
3865 enum ice_status
3866 ice_cfg_agg_bw_alloc(struct ice_port_info *pi, u32 agg_id, u8 ena_tcmap,
3867 enum ice_rl_type rl_type, u8 *bw_alloc)
3868 {
3869 struct ice_sched_agg_info *agg_info;
3870 bool agg_id_present = false;
3871 enum ice_status status = ICE_SUCCESS;
3872 struct ice_hw *hw = pi->hw;
3873 u8 tc;
3874
3875 ice_acquire_lock(&pi->sched_lock);
3876 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
3877 list_entry)
3878 if (agg_info->agg_id == agg_id) {
3879 agg_id_present = true;
3880 break;
3881 }
3882 if (!agg_id_present) {
3883 status = ICE_ERR_PARAM;
3884 goto exit_cfg_agg_bw_alloc;
3885 }
3886
3887 /* Return success if no nodes are present across TC */
3888 ice_for_each_traffic_class(tc) {
3889 struct ice_sched_node *tc_node, *agg_node;
3890
3891 if (!ice_is_tc_ena(ena_tcmap, tc))
3892 continue;
3893
3894 tc_node = ice_sched_get_tc_node(pi, tc);
3895 if (!tc_node)
3896 continue;
3897
3898 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
3899 if (!agg_node)
3900 continue;
3901
3902 status = ice_sched_cfg_node_bw_alloc(hw, agg_node, rl_type,
3903 bw_alloc[tc]);
3904 if (status)
3905 break;
3906 status = ice_sched_save_agg_bw_alloc(pi, agg_id, tc, rl_type,
3907 bw_alloc[tc]);
3908 if (status)
3909 break;
3910 }
3911
3912 exit_cfg_agg_bw_alloc:
3913 ice_release_lock(&pi->sched_lock);
3914 return status;
3915 }
3916
3917 /**
3918 * ice_sched_calc_wakeup - calculate RL profile wakeup parameter
3919 * @hw: pointer to the HW struct
3920 * @bw: bandwidth in Kbps
3921 *
3922 * This function calculates the wakeup parameter of RL profile.
3923 */
3924 static u16 ice_sched_calc_wakeup(struct ice_hw *hw, s32 bw)
3925 {
3926 s64 bytes_per_sec, wakeup_int, wakeup_a, wakeup_b, wakeup_f;
3927 s32 wakeup_f_int;
3928 u16 wakeup = 0;
3929
3930 /* Get the wakeup integer value */
3931 bytes_per_sec = DIV_S64(bw * 1000, BITS_PER_BYTE);
3932 wakeup_int = DIV_S64(hw->psm_clk_freq, bytes_per_sec);
3933 if (wakeup_int > 63) {
3934 wakeup = (u16)((1 << 15) | wakeup_int);
3935 } else {
3936 /* Calculate fraction value up to 4 decimals
3937 * Convert Integer value to a constant multiplier
3938 */
3939 wakeup_b = (s64)ICE_RL_PROF_MULTIPLIER * wakeup_int;
3940 wakeup_a = DIV_S64(ICE_RL_PROF_MULTIPLIER *
3941 hw->psm_clk_freq, bytes_per_sec);
3942
3943 /* Get Fraction value */
3944 wakeup_f = wakeup_a - wakeup_b;
3945
3946 /* Round up the Fractional value via Ceil(Fractional value) */
3947 if (wakeup_f > DIV_S64(ICE_RL_PROF_MULTIPLIER, 2))
3948 wakeup_f += 1;
3949
3950 wakeup_f_int = (s32)DIV_S64(wakeup_f * ICE_RL_PROF_FRACTION,
3951 ICE_RL_PROF_MULTIPLIER);
3952 wakeup |= (u16)(wakeup_int << 9);
3953 wakeup |= (u16)(0x1ff & wakeup_f_int);
3954 }
3955
3956 return wakeup;
3957 }
3958
3959 /**
3960 * ice_sched_bw_to_rl_profile - convert BW to profile parameters
3961 * @hw: pointer to the HW struct
3962 * @bw: bandwidth in Kbps
3963 * @profile: profile parameters to return
3964 *
3965 * This function converts the BW to profile structure format.
3966 */
3967 static enum ice_status
3968 ice_sched_bw_to_rl_profile(struct ice_hw *hw, u32 bw,
3969 struct ice_aqc_rl_profile_elem *profile)
3970 {
3971 enum ice_status status = ICE_ERR_PARAM;
3972 s64 bytes_per_sec, ts_rate, mv_tmp;
3973 bool found = false;
3974 s32 encode = 0;
3975 s64 mv = 0;
3976 s32 i;
3977
3978 /* Bw settings range is from 0.5Mb/sec to 100Gb/sec */
3979 if (bw < ICE_SCHED_MIN_BW || bw > ICE_SCHED_MAX_BW)
3980 return status;
3981
3982 /* Bytes per second from Kbps */
3983 bytes_per_sec = DIV_S64(bw * 1000, BITS_PER_BYTE);
3984
3985 /* encode is 6 bits but really useful are 5 bits */
3986 for (i = 0; i < 64; i++) {
3987 u64 pow_result = BIT_ULL(i);
3988
3989 ts_rate = DIV_S64(hw->psm_clk_freq,
3990 pow_result * ICE_RL_PROF_TS_MULTIPLIER);
3991 if (ts_rate <= 0)
3992 continue;
3993
3994 /* Multiplier value */
3995 mv_tmp = DIV_S64(bytes_per_sec * ICE_RL_PROF_MULTIPLIER,
3996 ts_rate);
3997
3998 /* Round to the nearest ICE_RL_PROF_MULTIPLIER */
3999 mv = round_up_64bit(mv_tmp, ICE_RL_PROF_MULTIPLIER);
4000
4001 /* First multiplier value greater than the given
4002 * accuracy bytes
4003 */
4004 if (mv > ICE_RL_PROF_ACCURACY_BYTES) {
4005 encode = i;
4006 found = true;
4007 break;
4008 }
4009 }
4010 if (found) {
4011 u16 wm;
4012
4013 wm = ice_sched_calc_wakeup(hw, bw);
4014 profile->rl_multiply = CPU_TO_LE16(mv);
4015 profile->wake_up_calc = CPU_TO_LE16(wm);
4016 profile->rl_encode = CPU_TO_LE16(encode);
4017 status = ICE_SUCCESS;
4018 } else {
4019 status = ICE_ERR_DOES_NOT_EXIST;
4020 }
4021
4022 return status;
4023 }
4024
4025 /**
4026 * ice_sched_add_rl_profile - add RL profile
4027 * @hw: pointer to the hardware structure
4028 * @rl_type: type of rate limit BW - min, max, or shared
4029 * @bw: bandwidth in Kbps - Kilo bits per sec
4030 * @layer_num: specifies in which layer to create profile
4031 *
4032 * This function first checks the existing list for corresponding BW
4033 * parameter. If it exists, it returns the associated profile otherwise
4034 * it creates a new rate limit profile for requested BW, and adds it to
4035 * the HW DB and local list. It returns the new profile or null on error.
4036 * The caller needs to hold the scheduler lock.
4037 */
4038 static struct ice_aqc_rl_profile_info *
4039 ice_sched_add_rl_profile(struct ice_hw *hw, enum ice_rl_type rl_type,
4040 u32 bw, u8 layer_num)
4041 {
4042 struct ice_aqc_rl_profile_info *rl_prof_elem;
4043 u16 profiles_added = 0, num_profiles = 1;
4044 struct ice_aqc_rl_profile_elem *buf;
4045 enum ice_status status;
4046 u8 profile_type;
4047
4048 if (layer_num >= ICE_AQC_TOPO_MAX_LEVEL_NUM)
4049 return NULL;
4050 switch (rl_type) {
4051 case ICE_MIN_BW:
4052 profile_type = ICE_AQC_RL_PROFILE_TYPE_CIR;
4053 break;
4054 case ICE_MAX_BW:
4055 profile_type = ICE_AQC_RL_PROFILE_TYPE_EIR;
4056 break;
4057 case ICE_SHARED_BW:
4058 profile_type = ICE_AQC_RL_PROFILE_TYPE_SRL;
4059 break;
4060 default:
4061 return NULL;
4062 }
4063
4064 if (!hw)
4065 return NULL;
4066 LIST_FOR_EACH_ENTRY(rl_prof_elem, &hw->rl_prof_list[layer_num],
4067 ice_aqc_rl_profile_info, list_entry)
4068 if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) ==
4069 profile_type && rl_prof_elem->bw == bw)
4070 /* Return existing profile ID info */
4071 return rl_prof_elem;
4072
4073 /* Create new profile ID */
4074 rl_prof_elem = (struct ice_aqc_rl_profile_info *)
4075 ice_malloc(hw, sizeof(*rl_prof_elem));
4076
4077 if (!rl_prof_elem)
4078 return NULL;
4079
4080 status = ice_sched_bw_to_rl_profile(hw, bw, &rl_prof_elem->profile);
4081 if (status != ICE_SUCCESS)
4082 goto exit_add_rl_prof;
4083
4084 rl_prof_elem->bw = bw;
4085 /* layer_num is zero relative, and fw expects level from 1 to 9 */
4086 rl_prof_elem->profile.level = layer_num + 1;
4087 rl_prof_elem->profile.flags = profile_type;
4088 rl_prof_elem->profile.max_burst_size = CPU_TO_LE16(hw->max_burst_size);
4089
4090 /* Create new entry in HW DB */
4091 buf = &rl_prof_elem->profile;
4092 status = ice_aq_add_rl_profile(hw, num_profiles, buf, sizeof(*buf),
4093 &profiles_added, NULL);
4094 if (status || profiles_added != num_profiles)
4095 goto exit_add_rl_prof;
4096
4097 /* Good entry - add in the list */
4098 rl_prof_elem->prof_id_ref = 0;
4099 LIST_ADD(&rl_prof_elem->list_entry, &hw->rl_prof_list[layer_num]);
4100 return rl_prof_elem;
4101
4102 exit_add_rl_prof:
4103 ice_free(hw, rl_prof_elem);
4104 return NULL;
4105 }
4106
4107 /**
4108 * ice_sched_cfg_node_bw_lmt - configure node sched params
4109 * @hw: pointer to the HW struct
4110 * @node: sched node to configure
4111 * @rl_type: rate limit type CIR, EIR, or shared
4112 * @rl_prof_id: rate limit profile ID
4113 *
4114 * This function configures node element's BW limit.
4115 */
4116 static enum ice_status
4117 ice_sched_cfg_node_bw_lmt(struct ice_hw *hw, struct ice_sched_node *node,
4118 enum ice_rl_type rl_type, u16 rl_prof_id)
4119 {
4120 struct ice_aqc_txsched_elem_data buf;
4121 struct ice_aqc_txsched_elem *data;
4122
4123 buf = node->info;
4124 data = &buf.data;
4125 switch (rl_type) {
4126 case ICE_MIN_BW:
4127 data->valid_sections |= ICE_AQC_ELEM_VALID_CIR;
4128 data->cir_bw.bw_profile_idx = CPU_TO_LE16(rl_prof_id);
4129 break;
4130 case ICE_MAX_BW:
4131 data->valid_sections |= ICE_AQC_ELEM_VALID_EIR;
4132 data->eir_bw.bw_profile_idx = CPU_TO_LE16(rl_prof_id);
4133 break;
4134 case ICE_SHARED_BW:
4135 data->valid_sections |= ICE_AQC_ELEM_VALID_SHARED;
4136 data->srl_id = CPU_TO_LE16(rl_prof_id);
4137 break;
4138 default:
4139 /* Unknown rate limit type */
4140 return ICE_ERR_PARAM;
4141 }
4142
4143 /* Configure element */
4144 return ice_sched_update_elem(hw, node, &buf);
4145 }
4146
4147 /**
4148 * ice_sched_get_node_rl_prof_id - get node's rate limit profile ID
4149 * @node: sched node
4150 * @rl_type: rate limit type
4151 *
4152 * If existing profile matches, it returns the corresponding rate
4153 * limit profile ID, otherwise it returns an invalid ID as error.
4154 */
4155 static u16
4156 ice_sched_get_node_rl_prof_id(struct ice_sched_node *node,
4157 enum ice_rl_type rl_type)
4158 {
4159 u16 rl_prof_id = ICE_SCHED_INVAL_PROF_ID;
4160 struct ice_aqc_txsched_elem *data;
4161
4162 data = &node->info.data;
4163 switch (rl_type) {
4164 case ICE_MIN_BW:
4165 if (data->valid_sections & ICE_AQC_ELEM_VALID_CIR)
4166 rl_prof_id = LE16_TO_CPU(data->cir_bw.bw_profile_idx);
4167 break;
4168 case ICE_MAX_BW:
4169 if (data->valid_sections & ICE_AQC_ELEM_VALID_EIR)
4170 rl_prof_id = LE16_TO_CPU(data->eir_bw.bw_profile_idx);
4171 break;
4172 case ICE_SHARED_BW:
4173 if (data->valid_sections & ICE_AQC_ELEM_VALID_SHARED)
4174 rl_prof_id = LE16_TO_CPU(data->srl_id);
4175 break;
4176 default:
4177 break;
4178 }
4179
4180 return rl_prof_id;
4181 }
4182
4183 /**
4184 * ice_sched_get_rl_prof_layer - selects rate limit profile creation layer
4185 * @pi: port information structure
4186 * @rl_type: type of rate limit BW - min, max, or shared
4187 * @layer_index: layer index
4188 *
4189 * This function returns requested profile creation layer.
4190 */
4191 static u8
4192 ice_sched_get_rl_prof_layer(struct ice_port_info *pi, enum ice_rl_type rl_type,
4193 u8 layer_index)
4194 {
4195 struct ice_hw *hw = pi->hw;
4196
4197 if (layer_index >= hw->num_tx_sched_layers)
4198 return ICE_SCHED_INVAL_LAYER_NUM;
4199 switch (rl_type) {
4200 case ICE_MIN_BW:
4201 if (hw->layer_info[layer_index].max_cir_rl_profiles)
4202 return layer_index;
4203 break;
4204 case ICE_MAX_BW:
4205 if (hw->layer_info[layer_index].max_eir_rl_profiles)
4206 return layer_index;
4207 break;
4208 case ICE_SHARED_BW:
4209 /* if current layer doesn't support SRL profile creation
4210 * then try a layer up or down.
4211 */
4212 if (hw->layer_info[layer_index].max_srl_profiles)
4213 return layer_index;
4214 else if (layer_index < hw->num_tx_sched_layers - 1 &&
4215 hw->layer_info[layer_index + 1].max_srl_profiles)
4216 return layer_index + 1;
4217 else if (layer_index > 0 &&
4218 hw->layer_info[layer_index - 1].max_srl_profiles)
4219 return layer_index - 1;
4220 break;
4221 default:
4222 break;
4223 }
4224 return ICE_SCHED_INVAL_LAYER_NUM;
4225 }
4226
4227 /**
4228 * ice_sched_get_srl_node - get shared rate limit node
4229 * @node: tree node
4230 * @srl_layer: shared rate limit layer
4231 *
4232 * This function returns SRL node to be used for shared rate limit purpose.
4233 * The caller needs to hold scheduler lock.
4234 */
4235 static struct ice_sched_node *
4236 ice_sched_get_srl_node(struct ice_sched_node *node, u8 srl_layer)
4237 {
4238 if (srl_layer > node->tx_sched_layer)
4239 return node->children[0];
4240 else if (srl_layer < node->tx_sched_layer)
4241 /* Node can't be created without a parent. It will always
4242 * have a valid parent except root node.
4243 */
4244 return node->parent;
4245 else
4246 return node;
4247 }
4248
4249 /**
4250 * ice_sched_rm_rl_profile - remove RL profile ID
4251 * @hw: pointer to the hardware structure
4252 * @layer_num: layer number where profiles are saved
4253 * @profile_type: profile type like EIR, CIR, or SRL
4254 * @profile_id: profile ID to remove
4255 *
4256 * This function removes rate limit profile from layer 'layer_num' of type
4257 * 'profile_type' and profile ID as 'profile_id'. The caller needs to hold
4258 * scheduler lock.
4259 */
4260 static enum ice_status
4261 ice_sched_rm_rl_profile(struct ice_hw *hw, u8 layer_num, u8 profile_type,
4262 u16 profile_id)
4263 {
4264 struct ice_aqc_rl_profile_info *rl_prof_elem;
4265 enum ice_status status = ICE_SUCCESS;
4266
4267 if (layer_num >= ICE_AQC_TOPO_MAX_LEVEL_NUM)
4268 return ICE_ERR_PARAM;
4269 /* Check the existing list for RL profile */
4270 LIST_FOR_EACH_ENTRY(rl_prof_elem, &hw->rl_prof_list[layer_num],
4271 ice_aqc_rl_profile_info, list_entry)
4272 if ((rl_prof_elem->profile.flags & ICE_AQC_RL_PROFILE_TYPE_M) ==
4273 profile_type &&
4274 LE16_TO_CPU(rl_prof_elem->profile.profile_id) ==
4275 profile_id) {
4276 if (rl_prof_elem->prof_id_ref)
4277 rl_prof_elem->prof_id_ref--;
4278
4279 /* Remove old profile ID from database */
4280 status = ice_sched_del_rl_profile(hw, rl_prof_elem);
4281 if (status && status != ICE_ERR_IN_USE)
4282 ice_debug(hw, ICE_DBG_SCHED, "Remove rl profile failed\n");
4283 break;
4284 }
4285 if (status == ICE_ERR_IN_USE)
4286 status = ICE_SUCCESS;
4287 return status;
4288 }
4289
4290 /**
4291 * ice_sched_set_node_bw_dflt - set node's bandwidth limit to default
4292 * @pi: port information structure
4293 * @node: pointer to node structure
4294 * @rl_type: rate limit type min, max, or shared
4295 * @layer_num: layer number where RL profiles are saved
4296 *
4297 * This function configures node element's BW rate limit profile ID of
4298 * type CIR, EIR, or SRL to default. This function needs to be called
4299 * with the scheduler lock held.
4300 */
4301 static enum ice_status
4302 ice_sched_set_node_bw_dflt(struct ice_port_info *pi,
4303 struct ice_sched_node *node,
4304 enum ice_rl_type rl_type, u8 layer_num)
4305 {
4306 enum ice_status status;
4307 struct ice_hw *hw;
4308 u8 profile_type;
4309 u16 rl_prof_id;
4310 u16 old_id;
4311
4312 hw = pi->hw;
4313 switch (rl_type) {
4314 case ICE_MIN_BW:
4315 profile_type = ICE_AQC_RL_PROFILE_TYPE_CIR;
4316 rl_prof_id = ICE_SCHED_DFLT_RL_PROF_ID;
4317 break;
4318 case ICE_MAX_BW:
4319 profile_type = ICE_AQC_RL_PROFILE_TYPE_EIR;
4320 rl_prof_id = ICE_SCHED_DFLT_RL_PROF_ID;
4321 break;
4322 case ICE_SHARED_BW:
4323 profile_type = ICE_AQC_RL_PROFILE_TYPE_SRL;
4324 /* No SRL is configured for default case */
4325 rl_prof_id = ICE_SCHED_NO_SHARED_RL_PROF_ID;
4326 break;
4327 default:
4328 return ICE_ERR_PARAM;
4329 }
4330 /* Save existing RL prof ID for later clean up */
4331 old_id = ice_sched_get_node_rl_prof_id(node, rl_type);
4332 /* Configure BW scheduling parameters */
4333 status = ice_sched_cfg_node_bw_lmt(hw, node, rl_type, rl_prof_id);
4334 if (status)
4335 return status;
4336
4337 /* Remove stale RL profile ID */
4338 if (old_id == ICE_SCHED_DFLT_RL_PROF_ID ||
4339 old_id == ICE_SCHED_INVAL_PROF_ID)
4340 return ICE_SUCCESS;
4341
4342 return ice_sched_rm_rl_profile(hw, layer_num, profile_type, old_id);
4343 }
4344
4345 /**
4346 * ice_sched_set_node_bw - set node's bandwidth
4347 * @pi: port information structure
4348 * @node: tree node
4349 * @rl_type: rate limit type min, max, or shared
4350 * @bw: bandwidth in Kbps - Kilo bits per sec
4351 * @layer_num: layer number
4352 *
4353 * This function adds new profile corresponding to requested BW, configures
4354 * node's RL profile ID of type CIR, EIR, or SRL, and removes old profile
4355 * ID from local database. The caller needs to hold scheduler lock.
4356 */
4357 static enum ice_status
4358 ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,
4359 enum ice_rl_type rl_type, u32 bw, u8 layer_num)
4360 {
4361 struct ice_aqc_rl_profile_info *rl_prof_info;
4362 enum ice_status status = ICE_ERR_PARAM;
4363 struct ice_hw *hw = pi->hw;
4364 u16 old_id, rl_prof_id;
4365
4366 rl_prof_info = ice_sched_add_rl_profile(hw, rl_type, bw, layer_num);
4367 if (!rl_prof_info)
4368 return status;
4369
4370 rl_prof_id = LE16_TO_CPU(rl_prof_info->profile.profile_id);
4371
4372 /* Save existing RL prof ID for later clean up */
4373 old_id = ice_sched_get_node_rl_prof_id(node, rl_type);
4374 /* Configure BW scheduling parameters */
4375 status = ice_sched_cfg_node_bw_lmt(hw, node, rl_type, rl_prof_id);
4376 if (status)
4377 return status;
4378
4379 /* New changes has been applied */
4380 /* Increment the profile ID reference count */
4381 rl_prof_info->prof_id_ref++;
4382
4383 /* Check for old ID removal */
4384 if ((old_id == ICE_SCHED_DFLT_RL_PROF_ID && rl_type != ICE_SHARED_BW) ||
4385 old_id == ICE_SCHED_INVAL_PROF_ID || old_id == rl_prof_id)
4386 return ICE_SUCCESS;
4387
4388 return ice_sched_rm_rl_profile(hw, layer_num,
4389 rl_prof_info->profile.flags &
4390 ICE_AQC_RL_PROFILE_TYPE_M, old_id);
4391 }
4392
4393 /**
4394 * ice_sched_set_node_bw_lmt - set node's BW limit
4395 * @pi: port information structure
4396 * @node: tree node
4397 * @rl_type: rate limit type min, max, or shared
4398 * @bw: bandwidth in Kbps - Kilo bits per sec
4399 *
4400 * It updates node's BW limit parameters like BW RL profile ID of type CIR,
4401 * EIR, or SRL. The caller needs to hold scheduler lock.
4402 *
4403 * NOTE: Caller provides the correct SRL node in case of shared profile
4404 * settings.
4405 */
4406 static enum ice_status
4407 ice_sched_set_node_bw_lmt(struct ice_port_info *pi, struct ice_sched_node *node,
4408 enum ice_rl_type rl_type, u32 bw)
4409 {
4410 struct ice_hw *hw;
4411 u8 layer_num;
4412
4413 if (!pi)
4414 return ICE_ERR_PARAM;
4415 hw = pi->hw;
4416 /* Remove unused RL profile IDs from HW and SW DB */
4417 ice_sched_rm_unused_rl_prof(hw);
4418
4419 layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
4420 node->tx_sched_layer);
4421 if (layer_num >= hw->num_tx_sched_layers)
4422 return ICE_ERR_PARAM;
4423
4424 if (bw == ICE_SCHED_DFLT_BW)
4425 return ice_sched_set_node_bw_dflt(pi, node, rl_type, layer_num);
4426 return ice_sched_set_node_bw(pi, node, rl_type, bw, layer_num);
4427 }
4428
4429 /**
4430 * ice_sched_set_node_bw_dflt_lmt - set node's BW limit to default
4431 * @pi: port information structure
4432 * @node: pointer to node structure
4433 * @rl_type: rate limit type min, max, or shared
4434 *
4435 * This function configures node element's BW rate limit profile ID of
4436 * type CIR, EIR, or SRL to default. This function needs to be called
4437 * with the scheduler lock held.
4438 */
4439 static enum ice_status
4440 ice_sched_set_node_bw_dflt_lmt(struct ice_port_info *pi,
4441 struct ice_sched_node *node,
4442 enum ice_rl_type rl_type)
4443 {
4444 return ice_sched_set_node_bw_lmt(pi, node, rl_type,
4445 ICE_SCHED_DFLT_BW);
4446 }
4447
4448 /**
4449 * ice_sched_validate_srl_node - Check node for SRL applicability
4450 * @node: sched node to configure
4451 * @sel_layer: selected SRL layer
4452 *
4453 * This function checks if the SRL can be applied to a selceted layer node on
4454 * behalf of the requested node (first argument). This function needs to be
4455 * called with scheduler lock held.
4456 */
4457 static enum ice_status
4458 ice_sched_validate_srl_node(struct ice_sched_node *node, u8 sel_layer)
4459 {
4460 /* SRL profiles are not available on all layers. Check if the
4461 * SRL profile can be applied to a node above or below the
4462 * requested node. SRL configuration is possible only if the
4463 * selected layer's node has single child.
4464 */
4465 if (sel_layer == node->tx_sched_layer ||
4466 ((sel_layer == node->tx_sched_layer + 1) &&
4467 node->num_children == 1) ||
4468 ((sel_layer == node->tx_sched_layer - 1) &&
4469 (node->parent && node->parent->num_children == 1)))
4470 return ICE_SUCCESS;
4471
4472 return ICE_ERR_CFG;
4473 }
4474
4475 /**
4476 * ice_sched_save_q_bw - save queue node's BW information
4477 * @q_ctx: queue context structure
4478 * @rl_type: rate limit type min, max, or shared
4479 * @bw: bandwidth in Kbps - Kilo bits per sec
4480 *
4481 * Save BW information of queue type node for post replay use.
4482 */
4483 static enum ice_status
4484 ice_sched_save_q_bw(struct ice_q_ctx *q_ctx, enum ice_rl_type rl_type, u32 bw)
4485 {
4486 switch (rl_type) {
4487 case ICE_MIN_BW:
4488 ice_set_clear_cir_bw(&q_ctx->bw_t_info, bw);
4489 break;
4490 case ICE_MAX_BW:
4491 ice_set_clear_eir_bw(&q_ctx->bw_t_info, bw);
4492 break;
4493 case ICE_SHARED_BW:
4494 ice_set_clear_shared_bw(&q_ctx->bw_t_info, bw);
4495 break;
4496 default:
4497 return ICE_ERR_PARAM;
4498 }
4499 return ICE_SUCCESS;
4500 }
4501
4502 /**
4503 * ice_sched_set_q_bw_lmt - sets queue BW limit
4504 * @pi: port information structure
4505 * @vsi_handle: sw VSI handle
4506 * @tc: traffic class
4507 * @q_handle: software queue handle
4508 * @rl_type: min, max, or shared
4509 * @bw: bandwidth in Kbps
4510 *
4511 * This function sets BW limit of queue scheduling node.
4512 */
4513 static enum ice_status
4514 ice_sched_set_q_bw_lmt(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
4515 u16 q_handle, enum ice_rl_type rl_type, u32 bw)
4516 {
4517 enum ice_status status = ICE_ERR_PARAM;
4518 struct ice_sched_node *node;
4519 struct ice_q_ctx *q_ctx;
4520
4521 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
4522 return ICE_ERR_PARAM;
4523 ice_acquire_lock(&pi->sched_lock);
4524 q_ctx = ice_get_lan_q_ctx(pi->hw, vsi_handle, tc, q_handle);
4525 if (!q_ctx)
4526 goto exit_q_bw_lmt;
4527 node = ice_sched_find_node_by_teid(pi->root, q_ctx->q_teid);
4528 if (!node) {
4529 ice_debug(pi->hw, ICE_DBG_SCHED, "Wrong q_teid\n");
4530 goto exit_q_bw_lmt;
4531 }
4532
4533 /* Return error if it is not a leaf node */
4534 if (node->info.data.elem_type != ICE_AQC_ELEM_TYPE_LEAF)
4535 goto exit_q_bw_lmt;
4536
4537 /* SRL bandwidth layer selection */
4538 if (rl_type == ICE_SHARED_BW) {
4539 u8 sel_layer; /* selected layer */
4540
4541 sel_layer = ice_sched_get_rl_prof_layer(pi, rl_type,
4542 node->tx_sched_layer);
4543 if (sel_layer >= pi->hw->num_tx_sched_layers) {
4544 status = ICE_ERR_PARAM;
4545 goto exit_q_bw_lmt;
4546 }
4547 status = ice_sched_validate_srl_node(node, sel_layer);
4548 if (status)
4549 goto exit_q_bw_lmt;
4550 }
4551
4552 if (bw == ICE_SCHED_DFLT_BW)
4553 status = ice_sched_set_node_bw_dflt_lmt(pi, node, rl_type);
4554 else
4555 status = ice_sched_set_node_bw_lmt(pi, node, rl_type, bw);
4556
4557 if (!status)
4558 status = ice_sched_save_q_bw(q_ctx, rl_type, bw);
4559
4560 exit_q_bw_lmt:
4561 ice_release_lock(&pi->sched_lock);
4562 return status;
4563 }
4564
4565 /**
4566 * ice_cfg_q_bw_lmt - configure queue BW limit
4567 * @pi: port information structure
4568 * @vsi_handle: sw VSI handle
4569 * @tc: traffic class
4570 * @q_handle: software queue handle
4571 * @rl_type: min, max, or shared
4572 * @bw: bandwidth in Kbps
4573 *
4574 * This function configures BW limit of queue scheduling node.
4575 */
4576 enum ice_status
4577 ice_cfg_q_bw_lmt(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
4578 u16 q_handle, enum ice_rl_type rl_type, u32 bw)
4579 {
4580 return ice_sched_set_q_bw_lmt(pi, vsi_handle, tc, q_handle, rl_type,
4581 bw);
4582 }
4583
4584 /**
4585 * ice_cfg_q_bw_dflt_lmt - configure queue BW default limit
4586 * @pi: port information structure
4587 * @vsi_handle: sw VSI handle
4588 * @tc: traffic class
4589 * @q_handle: software queue handle
4590 * @rl_type: min, max, or shared
4591 *
4592 * This function configures BW default limit of queue scheduling node.
4593 */
4594 enum ice_status
4595 ice_cfg_q_bw_dflt_lmt(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
4596 u16 q_handle, enum ice_rl_type rl_type)
4597 {
4598 return ice_sched_set_q_bw_lmt(pi, vsi_handle, tc, q_handle, rl_type,
4599 ICE_SCHED_DFLT_BW);
4600 }
4601
4602 /**
4603 * ice_sched_save_tc_node_bw - save TC node BW limit
4604 * @pi: port information structure
4605 * @tc: TC number
4606 * @rl_type: min or max
4607 * @bw: bandwidth in Kbps
4608 *
4609 * This function saves the modified values of bandwidth settings for later
4610 * replay purpose (restore) after reset.
4611 */
4612 static enum ice_status
4613 ice_sched_save_tc_node_bw(struct ice_port_info *pi, u8 tc,
4614 enum ice_rl_type rl_type, u32 bw)
4615 {
4616 if (tc >= ICE_MAX_TRAFFIC_CLASS)
4617 return ICE_ERR_PARAM;
4618 switch (rl_type) {
4619 case ICE_MIN_BW:
4620 ice_set_clear_cir_bw(&pi->tc_node_bw_t_info[tc], bw);
4621 break;
4622 case ICE_MAX_BW:
4623 ice_set_clear_eir_bw(&pi->tc_node_bw_t_info[tc], bw);
4624 break;
4625 case ICE_SHARED_BW:
4626 ice_set_clear_shared_bw(&pi->tc_node_bw_t_info[tc], bw);
4627 break;
4628 default:
4629 return ICE_ERR_PARAM;
4630 }
4631 return ICE_SUCCESS;
4632 }
4633
4634 /**
4635 * ice_sched_set_tc_node_bw_lmt - sets TC node BW limit
4636 * @pi: port information structure
4637 * @tc: TC number
4638 * @rl_type: min or max
4639 * @bw: bandwidth in Kbps
4640 *
4641 * This function configures bandwidth limit of TC node.
4642 */
4643 static enum ice_status
4644 ice_sched_set_tc_node_bw_lmt(struct ice_port_info *pi, u8 tc,
4645 enum ice_rl_type rl_type, u32 bw)
4646 {
4647 enum ice_status status = ICE_ERR_PARAM;
4648 struct ice_sched_node *tc_node;
4649
4650 if (tc >= ICE_MAX_TRAFFIC_CLASS)
4651 return status;
4652 ice_acquire_lock(&pi->sched_lock);
4653 tc_node = ice_sched_get_tc_node(pi, tc);
4654 if (!tc_node)
4655 goto exit_set_tc_node_bw;
4656 if (bw == ICE_SCHED_DFLT_BW)
4657 status = ice_sched_set_node_bw_dflt_lmt(pi, tc_node, rl_type);
4658 else
4659 status = ice_sched_set_node_bw_lmt(pi, tc_node, rl_type, bw);
4660 if (!status)
4661 status = ice_sched_save_tc_node_bw(pi, tc, rl_type, bw);
4662
4663 exit_set_tc_node_bw:
4664 ice_release_lock(&pi->sched_lock);
4665 return status;
4666 }
4667
4668 /**
4669 * ice_cfg_tc_node_bw_lmt - configure TC node BW limit
4670 * @pi: port information structure
4671 * @tc: TC number
4672 * @rl_type: min or max
4673 * @bw: bandwidth in Kbps
4674 *
4675 * This function configures BW limit of TC node.
4676 * Note: The minimum guaranteed reservation is done via DCBX.
4677 */
4678 enum ice_status
4679 ice_cfg_tc_node_bw_lmt(struct ice_port_info *pi, u8 tc,
4680 enum ice_rl_type rl_type, u32 bw)
4681 {
4682 return ice_sched_set_tc_node_bw_lmt(pi, tc, rl_type, bw);
4683 }
4684
4685 /**
4686 * ice_cfg_tc_node_bw_dflt_lmt - configure TC node BW default limit
4687 * @pi: port information structure
4688 * @tc: TC number
4689 * @rl_type: min or max
4690 *
4691 * This function configures BW default limit of TC node.
4692 */
4693 enum ice_status
4694 ice_cfg_tc_node_bw_dflt_lmt(struct ice_port_info *pi, u8 tc,
4695 enum ice_rl_type rl_type)
4696 {
4697 return ice_sched_set_tc_node_bw_lmt(pi, tc, rl_type, ICE_SCHED_DFLT_BW);
4698 }
4699
4700 /**
4701 * ice_sched_save_tc_node_bw_alloc - save TC node's BW alloc information
4702 * @pi: port information structure
4703 * @tc: traffic class
4704 * @rl_type: rate limit type min or max
4705 * @bw_alloc: Bandwidth allocation information
4706 *
4707 * Save BW alloc information of VSI type node for post replay use.
4708 */
4709 static enum ice_status
4710 ice_sched_save_tc_node_bw_alloc(struct ice_port_info *pi, u8 tc,
4711 enum ice_rl_type rl_type, u16 bw_alloc)
4712 {
4713 if (tc >= ICE_MAX_TRAFFIC_CLASS)
4714 return ICE_ERR_PARAM;
4715 switch (rl_type) {
4716 case ICE_MIN_BW:
4717 ice_set_clear_cir_bw_alloc(&pi->tc_node_bw_t_info[tc],
4718 bw_alloc);
4719 break;
4720 case ICE_MAX_BW:
4721 ice_set_clear_eir_bw_alloc(&pi->tc_node_bw_t_info[tc],
4722 bw_alloc);
4723 break;
4724 default:
4725 return ICE_ERR_PARAM;
4726 }
4727 return ICE_SUCCESS;
4728 }
4729
4730 /**
4731 * ice_sched_set_tc_node_bw_alloc - set TC node BW alloc
4732 * @pi: port information structure
4733 * @tc: TC number
4734 * @rl_type: min or max
4735 * @bw_alloc: bandwidth alloc
4736 *
4737 * This function configures bandwidth alloc of TC node, also saves the
4738 * changed settings for replay purpose, and return success if it succeeds
4739 * in modifying bandwidth alloc setting.
4740 */
4741 static enum ice_status
4742 ice_sched_set_tc_node_bw_alloc(struct ice_port_info *pi, u8 tc,
4743 enum ice_rl_type rl_type, u8 bw_alloc)
4744 {
4745 enum ice_status status = ICE_ERR_PARAM;
4746 struct ice_sched_node *tc_node;
4747
4748 if (tc >= ICE_MAX_TRAFFIC_CLASS)
4749 return status;
4750 ice_acquire_lock(&pi->sched_lock);
4751 tc_node = ice_sched_get_tc_node(pi, tc);
4752 if (!tc_node)
4753 goto exit_set_tc_node_bw_alloc;
4754 status = ice_sched_cfg_node_bw_alloc(pi->hw, tc_node, rl_type,
4755 bw_alloc);
4756 if (status)
4757 goto exit_set_tc_node_bw_alloc;
4758 status = ice_sched_save_tc_node_bw_alloc(pi, tc, rl_type, bw_alloc);
4759
4760 exit_set_tc_node_bw_alloc:
4761 ice_release_lock(&pi->sched_lock);
4762 return status;
4763 }
4764
4765 /**
4766 * ice_cfg_tc_node_bw_alloc - configure TC node BW alloc
4767 * @pi: port information structure
4768 * @tc: TC number
4769 * @rl_type: min or max
4770 * @bw_alloc: bandwidth alloc
4771 *
4772 * This function configures BW limit of TC node.
4773 * Note: The minimum guaranteed reservation is done via DCBX.
4774 */
4775 enum ice_status
4776 ice_cfg_tc_node_bw_alloc(struct ice_port_info *pi, u8 tc,
4777 enum ice_rl_type rl_type, u8 bw_alloc)
4778 {
4779 return ice_sched_set_tc_node_bw_alloc(pi, tc, rl_type, bw_alloc);
4780 }
4781
4782 /**
4783 * ice_sched_set_agg_bw_dflt_lmt - set aggregator node's BW limit to default
4784 * @pi: port information structure
4785 * @vsi_handle: software VSI handle
4786 *
4787 * This function retrieves the aggregator ID based on VSI ID and TC,
4788 * and sets node's BW limit to default. This function needs to be
4789 * called with the scheduler lock held.
4790 */
4791 enum ice_status
4792 ice_sched_set_agg_bw_dflt_lmt(struct ice_port_info *pi, u16 vsi_handle)
4793 {
4794 struct ice_vsi_ctx *vsi_ctx;
4795 enum ice_status status = ICE_SUCCESS;
4796 u8 tc;
4797
4798 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
4799 return ICE_ERR_PARAM;
4800 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
4801 if (!vsi_ctx)
4802 return ICE_ERR_PARAM;
4803
4804 ice_for_each_traffic_class(tc) {
4805 struct ice_sched_node *node;
4806
4807 node = vsi_ctx->sched.ag_node[tc];
4808 if (!node)
4809 continue;
4810
4811 /* Set min profile to default */
4812 status = ice_sched_set_node_bw_dflt_lmt(pi, node, ICE_MIN_BW);
4813 if (status)
4814 break;
4815
4816 /* Set max profile to default */
4817 status = ice_sched_set_node_bw_dflt_lmt(pi, node, ICE_MAX_BW);
4818 if (status)
4819 break;
4820
4821 /* Remove shared profile, if there is one */
4822 status = ice_sched_set_node_bw_dflt_lmt(pi, node,
4823 ICE_SHARED_BW);
4824 if (status)
4825 break;
4826 }
4827
4828 return status;
4829 }
4830
4831 /**
4832 * ice_sched_get_node_by_id_type - get node from ID type
4833 * @pi: port information structure
4834 * @id: identifier
4835 * @agg_type: type of aggregator
4836 * @tc: traffic class
4837 *
4838 * This function returns node identified by ID of type aggregator, and
4839 * based on traffic class (TC). This function needs to be called with
4840 * the scheduler lock held.
4841 */
4842 static struct ice_sched_node *
4843 ice_sched_get_node_by_id_type(struct ice_port_info *pi, u32 id,
4844 enum ice_agg_type agg_type, u8 tc)
4845 {
4846 struct ice_sched_node *node = NULL;
4847 struct ice_sched_node *child_node;
4848
4849 switch (agg_type) {
4850 case ICE_AGG_TYPE_VSI: {
4851 struct ice_vsi_ctx *vsi_ctx;
4852 u16 vsi_handle = (u16)id;
4853
4854 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
4855 break;
4856 /* Get sched_vsi_info */
4857 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
4858 if (!vsi_ctx)
4859 break;
4860 node = vsi_ctx->sched.vsi_node[tc];
4861 break;
4862 }
4863
4864 case ICE_AGG_TYPE_AGG: {
4865 struct ice_sched_node *tc_node;
4866
4867 tc_node = ice_sched_get_tc_node(pi, tc);
4868 if (tc_node)
4869 node = ice_sched_get_agg_node(pi, tc_node, id);
4870 break;
4871 }
4872
4873 case ICE_AGG_TYPE_Q:
4874 /* The current implementation allows single queue to modify */
4875 node = ice_sched_get_node(pi, id);
4876 break;
4877
4878 case ICE_AGG_TYPE_QG:
4879 /* The current implementation allows single qg to modify */
4880 child_node = ice_sched_get_node(pi, id);
4881 if (!child_node)
4882 break;
4883 node = child_node->parent;
4884 break;
4885
4886 default:
4887 break;
4888 }
4889
4890 return node;
4891 }
4892
4893 /**
4894 * ice_sched_set_node_bw_lmt_per_tc - set node BW limit per TC
4895 * @pi: port information structure
4896 * @id: ID (software VSI handle or AGG ID)
4897 * @agg_type: aggregator type (VSI or AGG type node)
4898 * @tc: traffic class
4899 * @rl_type: min or max
4900 * @bw: bandwidth in Kbps
4901 *
4902 * This function sets BW limit of VSI or Aggregator scheduling node
4903 * based on TC information from passed in argument BW.
4904 */
4905 enum ice_status
4906 ice_sched_set_node_bw_lmt_per_tc(struct ice_port_info *pi, u32 id,
4907 enum ice_agg_type agg_type, u8 tc,
4908 enum ice_rl_type rl_type, u32 bw)
4909 {
4910 enum ice_status status = ICE_ERR_PARAM;
4911 struct ice_sched_node *node;
4912
4913 if (!pi)
4914 return status;
4915
4916 if (rl_type == ICE_UNKNOWN_BW)
4917 return status;
4918
4919 ice_acquire_lock(&pi->sched_lock);
4920 node = ice_sched_get_node_by_id_type(pi, id, agg_type, tc);
4921 if (!node) {
4922 ice_debug(pi->hw, ICE_DBG_SCHED, "Wrong id, agg type, or tc\n");
4923 goto exit_set_node_bw_lmt_per_tc;
4924 }
4925 if (bw == ICE_SCHED_DFLT_BW)
4926 status = ice_sched_set_node_bw_dflt_lmt(pi, node, rl_type);
4927 else
4928 status = ice_sched_set_node_bw_lmt(pi, node, rl_type, bw);
4929
4930 exit_set_node_bw_lmt_per_tc:
4931 ice_release_lock(&pi->sched_lock);
4932 return status;
4933 }
4934
4935 /**
4936 * ice_sched_validate_vsi_srl_node - validate VSI SRL node
4937 * @pi: port information structure
4938 * @vsi_handle: software VSI handle
4939 *
4940 * This function validates SRL node of the VSI node if available SRL layer is
4941 * different than the VSI node layer on all TC(s).This function needs to be
4942 * called with scheduler lock held.
4943 */
4944 static enum ice_status
4945 ice_sched_validate_vsi_srl_node(struct ice_port_info *pi, u16 vsi_handle)
4946 {
4947 u8 sel_layer = ICE_SCHED_INVAL_LAYER_NUM;
4948 u8 tc;
4949
4950 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
4951 return ICE_ERR_PARAM;
4952
4953 /* Return success if no nodes are present across TC */
4954 ice_for_each_traffic_class(tc) {
4955 struct ice_sched_node *tc_node, *vsi_node;
4956 enum ice_rl_type rl_type = ICE_SHARED_BW;
4957 enum ice_status status;
4958
4959 tc_node = ice_sched_get_tc_node(pi, tc);
4960 if (!tc_node)
4961 continue;
4962
4963 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
4964 if (!vsi_node)
4965 continue;
4966
4967 /* SRL bandwidth layer selection */
4968 if (sel_layer == ICE_SCHED_INVAL_LAYER_NUM) {
4969 u8 node_layer = vsi_node->tx_sched_layer;
4970 u8 layer_num;
4971
4972 layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
4973 node_layer);
4974 if (layer_num >= pi->hw->num_tx_sched_layers)
4975 return ICE_ERR_PARAM;
4976 sel_layer = layer_num;
4977 }
4978
4979 status = ice_sched_validate_srl_node(vsi_node, sel_layer);
4980 if (status)
4981 return status;
4982 }
4983 return ICE_SUCCESS;
4984 }
4985
4986 /**
4987 * ice_sched_set_save_vsi_srl_node_bw - set VSI shared limit values
4988 * @pi: port information structure
4989 * @vsi_handle: software VSI handle
4990 * @tc: traffic class
4991 * @srl_node: sched node to configure
4992 * @rl_type: rate limit type minimum, maximum, or shared
4993 * @bw: minimum, maximum, or shared bandwidth in Kbps
4994 *
4995 * Configure shared rate limiter(SRL) of VSI type nodes across given traffic
4996 * class, and saves those value for later use for replaying purposes. The
4997 * caller holds the scheduler lock.
4998 */
4999 static enum ice_status
5000 ice_sched_set_save_vsi_srl_node_bw(struct ice_port_info *pi, u16 vsi_handle,
5001 u8 tc, struct ice_sched_node *srl_node,
5002 enum ice_rl_type rl_type, u32 bw)
5003 {
5004 enum ice_status status;
5005
5006 if (bw == ICE_SCHED_DFLT_BW) {
5007 status = ice_sched_set_node_bw_dflt_lmt(pi, srl_node, rl_type);
5008 } else {
5009 status = ice_sched_set_node_bw_lmt(pi, srl_node, rl_type, bw);
5010 if (status)
5011 return status;
5012 status = ice_sched_save_vsi_bw(pi, vsi_handle, tc, rl_type, bw);
5013 }
5014 return status;
5015 }
5016
5017 /**
5018 * ice_sched_set_vsi_node_srl_per_tc - set VSI node BW shared limit for tc
5019 * @pi: port information structure
5020 * @vsi_handle: software VSI handle
5021 * @tc: traffic class
5022 * @min_bw: minimum bandwidth in Kbps
5023 * @max_bw: maximum bandwidth in Kbps
5024 * @shared_bw: shared bandwidth in Kbps
5025 *
5026 * Configure shared rate limiter(SRL) of VSI type nodes across requested
5027 * traffic class for VSI matching handle. When BW value of ICE_SCHED_DFLT_BW
5028 * is passed, it removes the corresponding bw from the node. The caller
5029 * holds scheduler lock.
5030 */
5031 static enum ice_status
5032 ice_sched_set_vsi_node_srl_per_tc(struct ice_port_info *pi, u16 vsi_handle,
5033 u8 tc, u32 min_bw, u32 max_bw, u32 shared_bw)
5034 {
5035 struct ice_sched_node *tc_node, *vsi_node, *cfg_node;
5036 enum ice_status status;
5037 u8 layer_num;
5038
5039 tc_node = ice_sched_get_tc_node(pi, tc);
5040 if (!tc_node)
5041 return ICE_ERR_CFG;
5042
5043 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
5044 if (!vsi_node)
5045 return ICE_ERR_CFG;
5046
5047 layer_num = ice_sched_get_rl_prof_layer(pi, ICE_SHARED_BW,
5048 vsi_node->tx_sched_layer);
5049 if (layer_num >= pi->hw->num_tx_sched_layers)
5050 return ICE_ERR_PARAM;
5051
5052 /* SRL node may be different */
5053 cfg_node = ice_sched_get_srl_node(vsi_node, layer_num);
5054 if (!cfg_node)
5055 return ICE_ERR_CFG;
5056
5057 status = ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc,
5058 cfg_node, ICE_MIN_BW,
5059 min_bw);
5060 if (status)
5061 return status;
5062
5063 status = ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc,
5064 cfg_node, ICE_MAX_BW,
5065 max_bw);
5066 if (status)
5067 return status;
5068
5069 return ice_sched_set_save_vsi_srl_node_bw(pi, vsi_handle, tc, cfg_node,
5070 ICE_SHARED_BW, shared_bw);
5071 }
5072
5073 /**
5074 * ice_sched_set_vsi_bw_shared_lmt - set VSI BW shared limit
5075 * @pi: port information structure
5076 * @vsi_handle: software VSI handle
5077 * @min_bw: minimum bandwidth in Kbps
5078 * @max_bw: maximum bandwidth in Kbps
5079 * @shared_bw: shared bandwidth in Kbps
5080 *
5081 * Configure shared rate limiter(SRL) of all VSI type nodes across all traffic
5082 * classes for VSI matching handle. When BW value of ICE_SCHED_DFLT_BW is
5083 * passed, it removes those value(s) from the node.
5084 */
5085 enum ice_status
5086 ice_sched_set_vsi_bw_shared_lmt(struct ice_port_info *pi, u16 vsi_handle,
5087 u32 min_bw, u32 max_bw, u32 shared_bw)
5088 {
5089 enum ice_status status = ICE_SUCCESS;
5090 u8 tc;
5091
5092 if (!pi)
5093 return ICE_ERR_PARAM;
5094
5095 if (!ice_is_vsi_valid(pi->hw, vsi_handle))
5096 return ICE_ERR_PARAM;
5097
5098 ice_acquire_lock(&pi->sched_lock);
5099 status = ice_sched_validate_vsi_srl_node(pi, vsi_handle);
5100 if (status)
5101 goto exit_set_vsi_bw_shared_lmt;
5102 /* Return success if no nodes are present across TC */
5103 ice_for_each_traffic_class(tc) {
5104 struct ice_sched_node *tc_node, *vsi_node;
5105
5106 tc_node = ice_sched_get_tc_node(pi, tc);
5107 if (!tc_node)
5108 continue;
5109
5110 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
5111 if (!vsi_node)
5112 continue;
5113
5114 status = ice_sched_set_vsi_node_srl_per_tc(pi, vsi_handle, tc,
5115 min_bw, max_bw,
5116 shared_bw);
5117 if (status)
5118 break;
5119 }
5120
5121 exit_set_vsi_bw_shared_lmt:
5122 ice_release_lock(&pi->sched_lock);
5123 return status;
5124 }
5125
5126 /**
5127 * ice_sched_validate_agg_srl_node - validate AGG SRL node
5128 * @pi: port information structure
5129 * @agg_id: aggregator ID
5130 *
5131 * This function validates SRL node of the AGG node if available SRL layer is
5132 * different than the AGG node layer on all TC(s).This function needs to be
5133 * called with scheduler lock held.
5134 */
5135 static enum ice_status
5136 ice_sched_validate_agg_srl_node(struct ice_port_info *pi, u32 agg_id)
5137 {
5138 u8 sel_layer = ICE_SCHED_INVAL_LAYER_NUM;
5139 struct ice_sched_agg_info *agg_info;
5140 bool agg_id_present = false;
5141 enum ice_status status = ICE_SUCCESS;
5142 u8 tc;
5143
5144 LIST_FOR_EACH_ENTRY(agg_info, &pi->hw->agg_list, ice_sched_agg_info,
5145 list_entry)
5146 if (agg_info->agg_id == agg_id) {
5147 agg_id_present = true;
5148 break;
5149 }
5150 if (!agg_id_present)
5151 return ICE_ERR_PARAM;
5152 /* Return success if no nodes are present across TC */
5153 ice_for_each_traffic_class(tc) {
5154 struct ice_sched_node *tc_node, *agg_node;
5155 enum ice_rl_type rl_type = ICE_SHARED_BW;
5156
5157 tc_node = ice_sched_get_tc_node(pi, tc);
5158 if (!tc_node)
5159 continue;
5160
5161 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
5162 if (!agg_node)
5163 continue;
5164 /* SRL bandwidth layer selection */
5165 if (sel_layer == ICE_SCHED_INVAL_LAYER_NUM) {
5166 u8 node_layer = agg_node->tx_sched_layer;
5167 u8 layer_num;
5168
5169 layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
5170 node_layer);
5171 if (layer_num >= pi->hw->num_tx_sched_layers)
5172 return ICE_ERR_PARAM;
5173 sel_layer = layer_num;
5174 }
5175
5176 status = ice_sched_validate_srl_node(agg_node, sel_layer);
5177 if (status)
5178 break;
5179 }
5180 return status;
5181 }
5182
5183 /**
5184 * ice_sched_validate_agg_id - Validate aggregator id
5185 * @pi: port information structure
5186 * @agg_id: aggregator ID
5187 *
5188 * This function validates aggregator id. Caller holds the scheduler lock.
5189 */
5190 static enum ice_status
5191 ice_sched_validate_agg_id(struct ice_port_info *pi, u32 agg_id)
5192 {
5193 struct ice_sched_agg_info *agg_info;
5194 struct ice_sched_agg_info *tmp;
5195 bool agg_id_present = false;
5196 enum ice_status status;
5197
5198 status = ice_sched_validate_agg_srl_node(pi, agg_id);
5199 if (status)
5200 return status;
5201
5202 LIST_FOR_EACH_ENTRY_SAFE(agg_info, tmp, &pi->hw->agg_list,
5203 ice_sched_agg_info, list_entry)
5204 if (agg_info->agg_id == agg_id) {
5205 agg_id_present = true;
5206 break;
5207 }
5208
5209 if (!agg_id_present)
5210 return ICE_ERR_PARAM;
5211
5212 return ICE_SUCCESS;
5213 }
5214
5215 /**
5216 * ice_sched_set_save_agg_srl_node_bw - set aggregator shared limit values
5217 * @pi: port information structure
5218 * @agg_id: aggregator ID
5219 * @tc: traffic class
5220 * @srl_node: sched node to configure
5221 * @rl_type: rate limit type minimum, maximum, or shared
5222 * @bw: minimum, maximum, or shared bandwidth in Kbps
5223 *
5224 * Configure shared rate limiter(SRL) of aggregator type nodes across
5225 * requested traffic class, and saves those value for later use for
5226 * replaying purposes. The caller holds the scheduler lock.
5227 */
5228 static enum ice_status
5229 ice_sched_set_save_agg_srl_node_bw(struct ice_port_info *pi, u32 agg_id, u8 tc,
5230 struct ice_sched_node *srl_node,
5231 enum ice_rl_type rl_type, u32 bw)
5232 {
5233 enum ice_status status;
5234
5235 if (bw == ICE_SCHED_DFLT_BW) {
5236 status = ice_sched_set_node_bw_dflt_lmt(pi, srl_node, rl_type);
5237 } else {
5238 status = ice_sched_set_node_bw_lmt(pi, srl_node, rl_type, bw);
5239 if (status)
5240 return status;
5241 status = ice_sched_save_agg_bw(pi, agg_id, tc, rl_type, bw);
5242 }
5243 return status;
5244 }
5245
5246 /**
5247 * ice_sched_set_agg_node_srl_per_tc - set aggregator SRL per tc
5248 * @pi: port information structure
5249 * @agg_id: aggregator ID
5250 * @tc: traffic class
5251 * @min_bw: minimum bandwidth in Kbps
5252 * @max_bw: maximum bandwidth in Kbps
5253 * @shared_bw: shared bandwidth in Kbps
5254 *
5255 * This function configures the shared rate limiter(SRL) of aggregator type
5256 * node for a given traffic class for aggregator matching agg_id. When BW
5257 * value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the node. Caller
5258 * holds the scheduler lock.
5259 */
5260 static enum ice_status
5261 ice_sched_set_agg_node_srl_per_tc(struct ice_port_info *pi, u32 agg_id,
5262 u8 tc, u32 min_bw, u32 max_bw, u32 shared_bw)
5263 {
5264 struct ice_sched_node *tc_node, *agg_node, *cfg_node;
5265 enum ice_rl_type rl_type = ICE_SHARED_BW;
5266 enum ice_status status = ICE_ERR_CFG;
5267 u8 layer_num;
5268
5269 tc_node = ice_sched_get_tc_node(pi, tc);
5270 if (!tc_node)
5271 return ICE_ERR_CFG;
5272
5273 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
5274 if (!agg_node)
5275 return ICE_ERR_CFG;
5276
5277 layer_num = ice_sched_get_rl_prof_layer(pi, rl_type,
5278 agg_node->tx_sched_layer);
5279 if (layer_num >= pi->hw->num_tx_sched_layers)
5280 return ICE_ERR_PARAM;
5281
5282 /* SRL node may be different */
5283 cfg_node = ice_sched_get_srl_node(agg_node, layer_num);
5284 if (!cfg_node)
5285 return ICE_ERR_CFG;
5286
5287 status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
5288 ICE_MIN_BW, min_bw);
5289 if (status)
5290 return status;
5291
5292 status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
5293 ICE_MAX_BW, max_bw);
5294 if (status)
5295 return status;
5296
5297 status = ice_sched_set_save_agg_srl_node_bw(pi, agg_id, tc, cfg_node,
5298 ICE_SHARED_BW, shared_bw);
5299 return status;
5300 }
5301
5302 /**
5303 * ice_sched_set_agg_bw_shared_lmt - set aggregator BW shared limit
5304 * @pi: port information structure
5305 * @agg_id: aggregator ID
5306 * @min_bw: minimum bandwidth in Kbps
5307 * @max_bw: maximum bandwidth in Kbps
5308 * @shared_bw: shared bandwidth in Kbps
5309 *
5310 * This function configures the shared rate limiter(SRL) of all aggregator type
5311 * nodes across all traffic classes for aggregator matching agg_id. When
5312 * BW value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the
5313 * node(s).
5314 */
5315 enum ice_status
5316 ice_sched_set_agg_bw_shared_lmt(struct ice_port_info *pi, u32 agg_id,
5317 u32 min_bw, u32 max_bw, u32 shared_bw)
5318 {
5319 enum ice_status status;
5320 u8 tc;
5321
5322 if (!pi)
5323 return ICE_ERR_PARAM;
5324
5325 ice_acquire_lock(&pi->sched_lock);
5326 status = ice_sched_validate_agg_id(pi, agg_id);
5327 if (status)
5328 goto exit_agg_bw_shared_lmt;
5329
5330 /* Return success if no nodes are present across TC */
5331 ice_for_each_traffic_class(tc) {
5332 struct ice_sched_node *tc_node, *agg_node;
5333
5334 tc_node = ice_sched_get_tc_node(pi, tc);
5335 if (!tc_node)
5336 continue;
5337
5338 agg_node = ice_sched_get_agg_node(pi, tc_node, agg_id);
5339 if (!agg_node)
5340 continue;
5341
5342 status = ice_sched_set_agg_node_srl_per_tc(pi, agg_id, tc,
5343 min_bw, max_bw,
5344 shared_bw);
5345 if (status)
5346 break;
5347 }
5348
5349 exit_agg_bw_shared_lmt:
5350 ice_release_lock(&pi->sched_lock);
5351 return status;
5352 }
5353
5354 /**
5355 * ice_sched_set_agg_bw_shared_lmt_per_tc - set aggregator BW shared lmt per tc
5356 * @pi: port information structure
5357 * @agg_id: aggregator ID
5358 * @tc: traffic class
5359 * @min_bw: minimum bandwidth in Kbps
5360 * @max_bw: maximum bandwidth in Kbps
5361 * @shared_bw: shared bandwidth in Kbps
5362 *
5363 * This function configures the shared rate limiter(SRL) of aggregator type
5364 * node for a given traffic class for aggregator matching agg_id. When BW
5365 * value of ICE_SCHED_DFLT_BW is passed, it removes SRL from the node.
5366 */
5367 enum ice_status
5368 ice_sched_set_agg_bw_shared_lmt_per_tc(struct ice_port_info *pi, u32 agg_id,
5369 u8 tc, u32 min_bw, u32 max_bw,
5370 u32 shared_bw)
5371 {
5372 enum ice_status status;
5373
5374 if (!pi)
5375 return ICE_ERR_PARAM;
5376 ice_acquire_lock(&pi->sched_lock);
5377 status = ice_sched_validate_agg_id(pi, agg_id);
5378 if (status)
5379 goto exit_agg_bw_shared_lmt_per_tc;
5380
5381 status = ice_sched_set_agg_node_srl_per_tc(pi, agg_id, tc, min_bw,
5382 max_bw, shared_bw);
5383
5384 exit_agg_bw_shared_lmt_per_tc:
5385 ice_release_lock(&pi->sched_lock);
5386 return status;
5387 }
5388
5389 /**
5390 * ice_sched_cfg_sibl_node_prio - configure node sibling priority
5391 * @pi: port information structure
5392 * @node: sched node to configure
5393 * @priority: sibling priority
5394 *
5395 * This function configures node element's sibling priority only. This
5396 * function needs to be called with scheduler lock held.
5397 */
5398 enum ice_status
5399 ice_sched_cfg_sibl_node_prio(struct ice_port_info *pi,
5400 struct ice_sched_node *node, u8 priority)
5401 {
5402 struct ice_aqc_txsched_elem_data buf;
5403 struct ice_aqc_txsched_elem *data;
5404 struct ice_hw *hw = pi->hw;
5405 enum ice_status status;
5406
5407 if (!hw)
5408 return ICE_ERR_PARAM;
5409 buf = node->info;
5410 data = &buf.data;
5411 data->valid_sections |= ICE_AQC_ELEM_VALID_GENERIC;
5412 priority = (priority << ICE_AQC_ELEM_GENERIC_PRIO_S) &
5413 ICE_AQC_ELEM_GENERIC_PRIO_M;
5414 data->generic &= ~ICE_AQC_ELEM_GENERIC_PRIO_M;
5415 data->generic |= priority;
5416
5417 /* Configure element */
5418 status = ice_sched_update_elem(hw, node, &buf);
5419 return status;
5420 }
5421
5422 /**
5423 * ice_cfg_rl_burst_size - Set burst size value
5424 * @hw: pointer to the HW struct
5425 * @bytes: burst size in bytes
5426 *
5427 * This function configures/set the burst size to requested new value. The new
5428 * burst size value is used for future rate limit calls. It doesn't change the
5429 * existing or previously created RL profiles.
5430 */
5431 enum ice_status ice_cfg_rl_burst_size(struct ice_hw *hw, u32 bytes)
5432 {
5433 u16 burst_size_to_prog;
5434
5435 if (bytes < ICE_MIN_BURST_SIZE_ALLOWED ||
5436 bytes > ICE_MAX_BURST_SIZE_ALLOWED)
5437 return ICE_ERR_PARAM;
5438 if (ice_round_to_num(bytes, 64) <=
5439 ICE_MAX_BURST_SIZE_64_BYTE_GRANULARITY) {
5440 /* 64 byte granularity case */
5441 /* Disable MSB granularity bit */
5442 burst_size_to_prog = ICE_64_BYTE_GRANULARITY;
5443 /* round number to nearest 64 byte granularity */
5444 bytes = ice_round_to_num(bytes, 64);
5445 /* The value is in 64 byte chunks */
5446 burst_size_to_prog |= (u16)(bytes / 64);
5447 } else {
5448 /* k bytes granularity case */
5449 /* Enable MSB granularity bit */
5450 burst_size_to_prog = ICE_KBYTE_GRANULARITY;
5451 /* round number to nearest 1024 granularity */
5452 bytes = ice_round_to_num(bytes, 1024);
5453 /* check rounding doesn't go beyond allowed */
5454 if (bytes > ICE_MAX_BURST_SIZE_KBYTE_GRANULARITY)
5455 bytes = ICE_MAX_BURST_SIZE_KBYTE_GRANULARITY;
5456 /* The value is in k bytes */
5457 burst_size_to_prog |= (u16)(bytes / 1024);
5458 }
5459 hw->max_burst_size = burst_size_to_prog;
5460 return ICE_SUCCESS;
5461 }
5462
5463 /**
5464 * ice_sched_replay_node_prio - re-configure node priority
5465 * @hw: pointer to the HW struct
5466 * @node: sched node to configure
5467 * @priority: priority value
5468 *
5469 * This function configures node element's priority value. It
5470 * needs to be called with scheduler lock held.
5471 */
5472 static enum ice_status
5473 ice_sched_replay_node_prio(struct ice_hw *hw, struct ice_sched_node *node,
5474 u8 priority)
5475 {
5476 struct ice_aqc_txsched_elem_data buf;
5477 struct ice_aqc_txsched_elem *data;
5478 enum ice_status status;
5479
5480 buf = node->info;
5481 data = &buf.data;
5482 data->valid_sections |= ICE_AQC_ELEM_VALID_GENERIC;
5483 data->generic = priority;
5484
5485 /* Configure element */
5486 status = ice_sched_update_elem(hw, node, &buf);
5487 return status;
5488 }
5489
5490 /**
5491 * ice_sched_replay_node_bw - replay node(s) BW
5492 * @hw: pointer to the HW struct
5493 * @node: sched node to configure
5494 * @bw_t_info: BW type information
5495 *
5496 * This function restores node's BW from bw_t_info. The caller needs
5497 * to hold the scheduler lock.
5498 */
5499 static enum ice_status
5500 ice_sched_replay_node_bw(struct ice_hw *hw, struct ice_sched_node *node,
5501 struct ice_bw_type_info *bw_t_info)
5502 {
5503 struct ice_port_info *pi = hw->port_info;
5504 enum ice_status status = ICE_ERR_PARAM;
5505 u16 bw_alloc;
5506
5507 if (!node)
5508 return status;
5509 if (!ice_is_any_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_CNT))
5510 return ICE_SUCCESS;
5511 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_PRIO)) {
5512 status = ice_sched_replay_node_prio(hw, node,
5513 bw_t_info->generic);
5514 if (status)
5515 return status;
5516 }
5517 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_CIR)) {
5518 status = ice_sched_set_node_bw_lmt(pi, node, ICE_MIN_BW,
5519 bw_t_info->cir_bw.bw);
5520 if (status)
5521 return status;
5522 }
5523 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_CIR_WT)) {
5524 bw_alloc = bw_t_info->cir_bw.bw_alloc;
5525 status = ice_sched_cfg_node_bw_alloc(hw, node, ICE_MIN_BW,
5526 bw_alloc);
5527 if (status)
5528 return status;
5529 }
5530 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_EIR)) {
5531 status = ice_sched_set_node_bw_lmt(pi, node, ICE_MAX_BW,
5532 bw_t_info->eir_bw.bw);
5533 if (status)
5534 return status;
5535 }
5536 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_EIR_WT)) {
5537 bw_alloc = bw_t_info->eir_bw.bw_alloc;
5538 status = ice_sched_cfg_node_bw_alloc(hw, node, ICE_MAX_BW,
5539 bw_alloc);
5540 if (status)
5541 return status;
5542 }
5543 if (ice_is_bit_set(bw_t_info->bw_t_bitmap, ICE_BW_TYPE_SHARED))
5544 status = ice_sched_set_node_bw_lmt(pi, node, ICE_SHARED_BW,
5545 bw_t_info->shared_bw);
5546 return status;
5547 }
5548
5549 /**
5550 * ice_sched_replay_agg_bw - replay aggregator node(s) BW
5551 * @hw: pointer to the HW struct
5552 * @agg_info: aggregator data structure
5553 *
5554 * This function re-creates aggregator type nodes. The caller needs to hold
5555 * the scheduler lock.
5556 */
5557 static enum ice_status
5558 ice_sched_replay_agg_bw(struct ice_hw *hw, struct ice_sched_agg_info *agg_info)
5559 {
5560 struct ice_sched_node *tc_node, *agg_node;
5561 enum ice_status status = ICE_SUCCESS;
5562 u8 tc;
5563
5564 if (!agg_info)
5565 return ICE_ERR_PARAM;
5566 ice_for_each_traffic_class(tc) {
5567 if (!ice_is_any_bit_set(agg_info->bw_t_info[tc].bw_t_bitmap,
5568 ICE_BW_TYPE_CNT))
5569 continue;
5570 tc_node = ice_sched_get_tc_node(hw->port_info, tc);
5571 if (!tc_node) {
5572 status = ICE_ERR_PARAM;
5573 break;
5574 }
5575 agg_node = ice_sched_get_agg_node(hw->port_info, tc_node,
5576 agg_info->agg_id);
5577 if (!agg_node) {
5578 status = ICE_ERR_PARAM;
5579 break;
5580 }
5581 status = ice_sched_replay_node_bw(hw, agg_node,
5582 &agg_info->bw_t_info[tc]);
5583 if (status)
5584 break;
5585 }
5586 return status;
5587 }
5588
5589 /**
5590 * ice_sched_get_ena_tc_bitmap - get enabled TC bitmap
5591 * @pi: port info struct
5592 * @tc_bitmap: 8 bits TC bitmap to check
5593 * @ena_tc_bitmap: 8 bits enabled TC bitmap to return
5594 *
5595 * This function returns enabled TC bitmap in variable ena_tc_bitmap. Some TCs
5596 * may be missing, it returns enabled TCs. This function needs to be called with
5597 * scheduler lock held.
5598 */
5599 static void
5600 ice_sched_get_ena_tc_bitmap(struct ice_port_info *pi, ice_bitmap_t *tc_bitmap,
5601 ice_bitmap_t *ena_tc_bitmap)
5602 {
5603 u8 tc;
5604
5605 /* Some TC(s) may be missing after reset, adjust for replay */
5606 ice_for_each_traffic_class(tc)
5607 if (ice_is_tc_ena(*tc_bitmap, tc) &&
5608 (ice_sched_get_tc_node(pi, tc)))
5609 ice_set_bit(tc, ena_tc_bitmap);
5610 }
5611
5612 /**
5613 * ice_sched_replay_agg - recreate aggregator node(s)
5614 * @hw: pointer to the HW struct
5615 *
5616 * This function recreate aggregator type nodes which are not replayed earlier.
5617 * It also replay aggregator BW information. These aggregator nodes are not
5618 * associated with VSI type node yet.
5619 */
5620 void ice_sched_replay_agg(struct ice_hw *hw)
5621 {
5622 struct ice_port_info *pi = hw->port_info;
5623 struct ice_sched_agg_info *agg_info;
5624
5625 ice_acquire_lock(&pi->sched_lock);
5626 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
5627 list_entry)
5628 /* replay aggregator (re-create aggregator node) */
5629 if (!ice_cmp_bitmap(agg_info->tc_bitmap,
5630 agg_info->replay_tc_bitmap,
5631 ICE_MAX_TRAFFIC_CLASS)) {
5632 ice_declare_bitmap(replay_bitmap,
5633 ICE_MAX_TRAFFIC_CLASS);
5634 enum ice_status status;
5635
5636 ice_zero_bitmap(replay_bitmap, ICE_MAX_TRAFFIC_CLASS);
5637 ice_sched_get_ena_tc_bitmap(pi,
5638 agg_info->replay_tc_bitmap,
5639 replay_bitmap);
5640 status = ice_sched_cfg_agg(hw->port_info,
5641 agg_info->agg_id,
5642 ICE_AGG_TYPE_AGG,
5643 replay_bitmap);
5644 if (status) {
5645 ice_info(hw, "Replay agg id[%d] failed\n",
5646 agg_info->agg_id);
5647 /* Move on to next one */
5648 continue;
5649 }
5650 /* Replay aggregator node BW (restore aggregator BW) */
5651 status = ice_sched_replay_agg_bw(hw, agg_info);
5652 if (status)
5653 ice_info(hw, "Replay agg bw [id=%d] failed\n",
5654 agg_info->agg_id);
5655 }
5656 ice_release_lock(&pi->sched_lock);
5657 }
5658
5659 /**
5660 * ice_sched_replay_agg_vsi_preinit - Agg/VSI replay pre initialization
5661 * @hw: pointer to the HW struct
5662 *
5663 * This function initialize aggregator(s) TC bitmap to zero. A required
5664 * preinit step for replaying aggregators.
5665 */
5666 void ice_sched_replay_agg_vsi_preinit(struct ice_hw *hw)
5667 {
5668 struct ice_port_info *pi = hw->port_info;
5669 struct ice_sched_agg_info *agg_info;
5670
5671 ice_acquire_lock(&pi->sched_lock);
5672 LIST_FOR_EACH_ENTRY(agg_info, &hw->agg_list, ice_sched_agg_info,
5673 list_entry) {
5674 struct ice_sched_agg_vsi_info *agg_vsi_info;
5675
5676 agg_info->tc_bitmap[0] = 0;
5677 LIST_FOR_EACH_ENTRY(agg_vsi_info, &agg_info->agg_vsi_list,
5678 ice_sched_agg_vsi_info, list_entry)
5679 agg_vsi_info->tc_bitmap[0] = 0;
5680 }
5681 ice_release_lock(&pi->sched_lock);
5682 }
5683
5684 /**
5685 * ice_sched_replay_root_node_bw - replay root node BW
5686 * @pi: port information structure
5687 *
5688 * Replay root node BW settings.
5689 */
5690 enum ice_status ice_sched_replay_root_node_bw(struct ice_port_info *pi)
5691 {
5692 enum ice_status status = ICE_SUCCESS;
5693
5694 if (!pi->hw)
5695 return ICE_ERR_PARAM;
5696 ice_acquire_lock(&pi->sched_lock);
5697
5698 status = ice_sched_replay_node_bw(pi->hw, pi->root,
5699 &pi->root_node_bw_t_info);
5700 ice_release_lock(&pi->sched_lock);
5701 return status;
5702 }
5703
5704 /**
5705 * ice_sched_replay_tc_node_bw - replay TC node(s) BW
5706 * @pi: port information structure
5707 *
5708 * This function replay TC nodes.
5709 */
5710 enum ice_status ice_sched_replay_tc_node_bw(struct ice_port_info *pi)
5711 {
5712 enum ice_status status = ICE_SUCCESS;
5713 u8 tc;
5714
5715 if (!pi->hw)
5716 return ICE_ERR_PARAM;
5717 ice_acquire_lock(&pi->sched_lock);
5718 ice_for_each_traffic_class(tc) {
5719 struct ice_sched_node *tc_node;
5720
5721 tc_node = ice_sched_get_tc_node(pi, tc);
5722 if (!tc_node)
5723 continue; /* TC not present */
5724 status = ice_sched_replay_node_bw(pi->hw, tc_node,
5725 &pi->tc_node_bw_t_info[tc]);
5726 if (status)
5727 break;
5728 }
5729 ice_release_lock(&pi->sched_lock);
5730 return status;
5731 }
5732
5733 /**
5734 * ice_sched_replay_vsi_bw - replay VSI type node(s) BW
5735 * @hw: pointer to the HW struct
5736 * @vsi_handle: software VSI handle
5737 * @tc_bitmap: 8 bits TC bitmap
5738 *
5739 * This function replays VSI type nodes bandwidth. This function needs to be
5740 * called with scheduler lock held.
5741 */
5742 static enum ice_status
5743 ice_sched_replay_vsi_bw(struct ice_hw *hw, u16 vsi_handle,
5744 ice_bitmap_t *tc_bitmap)
5745 {
5746 struct ice_sched_node *vsi_node, *tc_node;
5747 struct ice_port_info *pi = hw->port_info;
5748 struct ice_bw_type_info *bw_t_info;
5749 struct ice_vsi_ctx *vsi_ctx;
5750 enum ice_status status = ICE_SUCCESS;
5751 u8 tc;
5752
5753 vsi_ctx = ice_get_vsi_ctx(pi->hw, vsi_handle);
5754 if (!vsi_ctx)
5755 return ICE_ERR_PARAM;
5756 ice_for_each_traffic_class(tc) {
5757 if (!ice_is_tc_ena(*tc_bitmap, tc))
5758 continue;
5759 tc_node = ice_sched_get_tc_node(pi, tc);
5760 if (!tc_node)
5761 continue;
5762 vsi_node = ice_sched_get_vsi_node(pi, tc_node, vsi_handle);
5763 if (!vsi_node)
5764 continue;
5765 bw_t_info = &vsi_ctx->sched.bw_t_info[tc];
5766 status = ice_sched_replay_node_bw(hw, vsi_node, bw_t_info);
5767 if (status)
5768 break;
5769 }
5770 return status;
5771 }
5772
5773 /**
5774 * ice_sched_replay_vsi_agg - replay aggregator & VSI to aggregator node(s)
5775 * @hw: pointer to the HW struct
5776 * @vsi_handle: software VSI handle
5777 *
5778 * This function replays aggregator node, VSI to aggregator type nodes, and
5779 * their node bandwidth information. This function needs to be called with
5780 * scheduler lock held.
5781 */
5782 static enum ice_status
5783 ice_sched_replay_vsi_agg(struct ice_hw *hw, u16 vsi_handle)
5784 {
5785 ice_declare_bitmap(replay_bitmap, ICE_MAX_TRAFFIC_CLASS);
5786 struct ice_sched_agg_vsi_info *agg_vsi_info;
5787 struct ice_port_info *pi = hw->port_info;
5788 struct ice_sched_agg_info *agg_info;
5789 enum ice_status status;
5790
5791 ice_zero_bitmap(replay_bitmap, ICE_MAX_TRAFFIC_CLASS);
5792 if (!ice_is_vsi_valid(hw, vsi_handle))
5793 return ICE_ERR_PARAM;
5794 agg_info = ice_get_vsi_agg_info(hw, vsi_handle);
5795 if (!agg_info)
5796 return ICE_SUCCESS; /* Not present in list - default Agg case */
5797 agg_vsi_info = ice_get_agg_vsi_info(agg_info, vsi_handle);
5798 if (!agg_vsi_info)
5799 return ICE_SUCCESS; /* Not present in list - default Agg case */
5800 ice_sched_get_ena_tc_bitmap(pi, agg_info->replay_tc_bitmap,
5801 replay_bitmap);
5802 /* Replay aggregator node associated to vsi_handle */
5803 status = ice_sched_cfg_agg(hw->port_info, agg_info->agg_id,
5804 ICE_AGG_TYPE_AGG, replay_bitmap);
5805 if (status)
5806 return status;
5807 /* Replay aggregator node BW (restore aggregator BW) */
5808 status = ice_sched_replay_agg_bw(hw, agg_info);
5809 if (status)
5810 return status;
5811
5812 ice_zero_bitmap(replay_bitmap, ICE_MAX_TRAFFIC_CLASS);
5813 ice_sched_get_ena_tc_bitmap(pi, agg_vsi_info->replay_tc_bitmap,
5814 replay_bitmap);
5815 /* Move this VSI (vsi_handle) to above aggregator */
5816 status = ice_sched_assoc_vsi_to_agg(pi, agg_info->agg_id, vsi_handle,
5817 replay_bitmap);
5818 if (status)
5819 return status;
5820 /* Replay VSI BW (restore VSI BW) */
5821 return ice_sched_replay_vsi_bw(hw, vsi_handle,
5822 agg_vsi_info->tc_bitmap);
5823 }
5824
5825 /**
5826 * ice_replay_vsi_agg - replay VSI to aggregator node
5827 * @hw: pointer to the HW struct
5828 * @vsi_handle: software VSI handle
5829 *
5830 * This function replays association of VSI to aggregator type nodes, and
5831 * node bandwidth information.
5832 */
5833 enum ice_status ice_replay_vsi_agg(struct ice_hw *hw, u16 vsi_handle)
5834 {
5835 struct ice_port_info *pi = hw->port_info;
5836 enum ice_status status;
5837
5838 ice_acquire_lock(&pi->sched_lock);
5839 status = ice_sched_replay_vsi_agg(hw, vsi_handle);
5840 ice_release_lock(&pi->sched_lock);
5841 return status;
5842 }
5843
5844 /**
5845 * ice_sched_replay_q_bw - replay queue type node BW
5846 * @pi: port information structure
5847 * @q_ctx: queue context structure
5848 *
5849 * This function replays queue type node bandwidth. This function needs to be
5850 * called with scheduler lock held.
5851 */
5852 enum ice_status
5853 ice_sched_replay_q_bw(struct ice_port_info *pi, struct ice_q_ctx *q_ctx)
5854 {
5855 struct ice_sched_node *q_node;
5856
5857 /* Following also checks the presence of node in tree */
5858 q_node = ice_sched_find_node_by_teid(pi->root, q_ctx->q_teid);
5859 if (!q_node)
5860 return ICE_ERR_PARAM;
5861 return ice_sched_replay_node_bw(pi->hw, q_node, &q_ctx->bw_t_info);
5862 }
Cache object: ae7fc1c8acdd36ae332a365a93413472
|