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