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