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