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