aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/ice/ice_sched.c
diff options
context:
space:
mode:
authorAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>2018-03-20 10:58:17 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-03-26 15:21:42 -0400
commit5513b920a4f7869acffc8e6d800aebee608409e0 (patch)
tree6ccfa4e428c74db963668846c725ea8b4270d691 /drivers/net/ethernet/intel/ice/ice_sched.c
parentfcea6f3da546b93050f3534aadea7bd96c1d7349 (diff)
ice: Update Tx scheduler tree for VSI multi-Tx queue support
This patch adds the ability for a VSI to use multiple Tx queues. More specifically, the patch 1) Provides the ability to update the Tx scheduler tree in the firmware. The driver can configure the Tx scheduler tree by adding/removing multiple Tx queues per TC per VSI. 2) Allows a VSI to reconfigure its Tx queues during runtime. 3) Synchronizes the Tx scheduler update operations using locks. Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Tony Brelinski <tonyx.brelinski@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_sched.c')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sched.c886
1 files changed, 886 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
index e50eebbf78e3..f16ff3e4a840 100644
--- a/drivers/net/ethernet/intel/ice/ice_sched.c
+++ b/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -360,6 +360,110 @@ ice_aq_get_dflt_topo(struct ice_hw *hw, u8 lport,
360} 360}
361 361
362/** 362/**
363 * ice_aq_add_sched_elems - adds scheduling element
364 * @hw: pointer to the hw struct
365 * @grps_req: the number of groups that are requested to be added
366 * @buf: pointer to buffer
367 * @buf_size: buffer size in bytes
368 * @grps_added: returns total number of groups added
369 * @cd: pointer to command details structure or NULL
370 *
371 * Add scheduling elements (0x0401)
372 */
373static enum ice_status
374ice_aq_add_sched_elems(struct ice_hw *hw, u16 grps_req,
375 struct ice_aqc_add_elem *buf, u16 buf_size,
376 u16 *grps_added, struct ice_sq_cd *cd)
377{
378 struct ice_aqc_add_move_delete_elem *cmd;
379 struct ice_aq_desc desc;
380 enum ice_status status;
381
382 cmd = &desc.params.add_move_delete_elem;
383 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_sched_elems);
384 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
385
386 cmd->num_grps_req = cpu_to_le16(grps_req);
387 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
388 if (!status && grps_added)
389 *grps_added = le16_to_cpu(cmd->num_grps_updated);
390
391 return status;
392}
393
394/**
395 * ice_suspend_resume_elems - suspend/resume scheduler elements
396 * @hw: pointer to the hw struct
397 * @elems_req: number of elements to suspend
398 * @buf: pointer to buffer
399 * @buf_size: buffer size in bytes
400 * @elems_ret: returns total number of elements suspended
401 * @cd: pointer to command details structure or NULL
402 * @cmd_code: command code for suspend or resume
403 *
404 * suspend/resume scheduler elements
405 */
406static enum ice_status
407ice_suspend_resume_elems(struct ice_hw *hw, u16 elems_req,
408 struct ice_aqc_suspend_resume_elem *buf, u16 buf_size,
409 u16 *elems_ret, struct ice_sq_cd *cd,
410 enum ice_adminq_opc cmd_code)
411{
412 struct ice_aqc_get_cfg_elem *cmd;
413 struct ice_aq_desc desc;
414 enum ice_status status;
415
416 cmd = &desc.params.get_update_elem;
417 ice_fill_dflt_direct_cmd_desc(&desc, cmd_code);
418 cmd->num_elem_req = cpu_to_le16(elems_req);
419 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
420 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
421 if (!status && elems_ret)
422 *elems_ret = le16_to_cpu(cmd->num_elem_resp);
423 return status;
424}
425
426/**
427 * ice_aq_suspend_sched_elems - suspend scheduler elements
428 * @hw: pointer to the hw struct
429 * @elems_req: number of elements to suspend
430 * @buf: pointer to buffer
431 * @buf_size: buffer size in bytes
432 * @elems_ret: returns total number of elements suspended
433 * @cd: pointer to command details structure or NULL
434 *
435 * Suspend scheduling elements (0x0409)
436 */
437static enum ice_status
438ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req,
439 struct ice_aqc_suspend_resume_elem *buf,
440 u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
441{
442 return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret,
443 cd, ice_aqc_opc_suspend_sched_elems);
444}
445
446/**
447 * ice_aq_resume_sched_elems - resume scheduler elements
448 * @hw: pointer to the hw struct
449 * @elems_req: number of elements to resume
450 * @buf: pointer to buffer
451 * @buf_size: buffer size in bytes
452 * @elems_ret: returns total number of elements resumed
453 * @cd: pointer to command details structure or NULL
454 *
455 * resume scheduling elements (0x040A)
456 */
457static enum ice_status
458ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req,
459 struct ice_aqc_suspend_resume_elem *buf,
460 u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd)
461{
462 return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret,
463 cd, ice_aqc_opc_resume_sched_elems);
464}
465
466/**
363 * ice_aq_query_sched_res - query scheduler resource 467 * ice_aq_query_sched_res - query scheduler resource
364 * @hw: pointer to the hw struct 468 * @hw: pointer to the hw struct
365 * @buf_size: buffer size in bytes 469 * @buf_size: buffer size in bytes
@@ -380,6 +484,46 @@ ice_aq_query_sched_res(struct ice_hw *hw, u16 buf_size,
380} 484}
381 485
382/** 486/**
487 * ice_sched_suspend_resume_elems - suspend or resume hw nodes
488 * @hw: pointer to the hw struct
489 * @num_nodes: number of nodes
490 * @node_teids: array of node teids to be suspended or resumed
491 * @suspend: true means suspend / false means resume
492 *
493 * This function suspends or resumes hw nodes
494 */
495static enum ice_status
496ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids,
497 bool suspend)
498{
499 struct ice_aqc_suspend_resume_elem *buf;
500 u16 i, buf_size, num_elem_ret = 0;
501 enum ice_status status;
502
503 buf_size = sizeof(*buf) * num_nodes;
504 buf = devm_kzalloc(ice_hw_to_dev(hw), buf_size, GFP_KERNEL);
505 if (!buf)
506 return ICE_ERR_NO_MEMORY;
507
508 for (i = 0; i < num_nodes; i++)
509 buf->teid[i] = cpu_to_le32(node_teids[i]);
510
511 if (suspend)
512 status = ice_aq_suspend_sched_elems(hw, num_nodes, buf,
513 buf_size, &num_elem_ret,
514 NULL);
515 else
516 status = ice_aq_resume_sched_elems(hw, num_nodes, buf,
517 buf_size, &num_elem_ret,
518 NULL);
519 if (status || num_elem_ret != num_nodes)
520 ice_debug(hw, ICE_DBG_SCHED, "suspend/resume failed\n");
521
522 devm_kfree(ice_hw_to_dev(hw), buf);
523 return status;
524}
525
526/**
383 * ice_sched_clear_tx_topo - clears the schduler tree nodes 527 * ice_sched_clear_tx_topo - clears the schduler tree nodes
384 * @pi: port information structure 528 * @pi: port information structure
385 * 529 *
@@ -463,6 +607,215 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
463} 607}
464 608
465/** 609/**
610 * ice_sched_create_vsi_info_entry - create an empty new VSI entry
611 * @pi: port information structure
612 * @vsi_id: VSI Id
613 *
614 * This function creates a new VSI entry and adds it to list
615 */
616static struct ice_sched_vsi_info *
617ice_sched_create_vsi_info_entry(struct ice_port_info *pi, u16 vsi_id)
618{
619 struct ice_sched_vsi_info *vsi_elem;
620
621 if (!pi)
622 return NULL;
623
624 vsi_elem = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*vsi_elem),
625 GFP_KERNEL);
626 if (!vsi_elem)
627 return NULL;
628
629 list_add(&vsi_elem->list_entry, &pi->vsi_info_list);
630 vsi_elem->vsi_id = vsi_id;
631 return vsi_elem;
632}
633
634/**
635 * ice_sched_add_elems - add nodes to hw and SW DB
636 * @pi: port information structure
637 * @tc_node: pointer to the branch node
638 * @parent: pointer to the parent node
639 * @layer: layer number to add nodes
640 * @num_nodes: number of nodes
641 * @num_nodes_added: pointer to num nodes added
642 * @first_node_teid: if new nodes are added then return the teid of first node
643 *
644 * This function add nodes to hw as well as to SW DB for a given layer
645 */
646static enum ice_status
647ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
648 struct ice_sched_node *parent, u8 layer, u16 num_nodes,
649 u16 *num_nodes_added, u32 *first_node_teid)
650{
651 struct ice_sched_node *prev, *new_node;
652 struct ice_aqc_add_elem *buf;
653 u16 i, num_groups_added = 0;
654 enum ice_status status = 0;
655 struct ice_hw *hw = pi->hw;
656 u16 buf_size;
657 u32 teid;
658
659 buf_size = sizeof(*buf) + sizeof(*buf->generic) * (num_nodes - 1);
660 buf = devm_kzalloc(ice_hw_to_dev(hw), buf_size, GFP_KERNEL);
661 if (!buf)
662 return ICE_ERR_NO_MEMORY;
663
664 buf->hdr.parent_teid = parent->info.node_teid;
665 buf->hdr.num_elems = cpu_to_le16(num_nodes);
666 for (i = 0; i < num_nodes; i++) {
667 buf->generic[i].parent_teid = parent->info.node_teid;
668 buf->generic[i].data.elem_type = ICE_AQC_ELEM_TYPE_SE_GENERIC;
669 buf->generic[i].data.valid_sections =
670 ICE_AQC_ELEM_VALID_GENERIC | ICE_AQC_ELEM_VALID_CIR |
671 ICE_AQC_ELEM_VALID_EIR;
672 buf->generic[i].data.generic = 0;
673 buf->generic[i].data.cir_bw.bw_profile_idx =
674 ICE_SCHED_DFLT_RL_PROF_ID;
675 buf->generic[i].data.eir_bw.bw_profile_idx =
676 ICE_SCHED_DFLT_RL_PROF_ID;
677 }
678
679 status = ice_aq_add_sched_elems(hw, 1, buf, buf_size,
680 &num_groups_added, NULL);
681 if (status || num_groups_added != 1) {
682 ice_debug(hw, ICE_DBG_SCHED, "add elements failed\n");
683 devm_kfree(ice_hw_to_dev(hw), buf);
684 return ICE_ERR_CFG;
685 }
686
687 *num_nodes_added = num_nodes;
688 /* add nodes to the SW DB */
689 for (i = 0; i < num_nodes; i++) {
690 status = ice_sched_add_node(pi, layer, &buf->generic[i]);
691 if (status) {
692 ice_debug(hw, ICE_DBG_SCHED,
693 "add nodes in SW DB failed status =%d\n",
694 status);
695 break;
696 }
697
698 teid = le32_to_cpu(buf->generic[i].node_teid);
699 new_node = ice_sched_find_node_by_teid(parent, teid);
700
701 if (!new_node) {
702 ice_debug(hw, ICE_DBG_SCHED,
703 "Node is missing for teid =%d\n", teid);
704 break;
705 }
706
707 new_node->sibling = NULL;
708 new_node->tc_num = tc_node->tc_num;
709
710 /* add it to previous node sibling pointer */
711 /* Note: siblings are not linked across branches */
712 prev = ice_sched_get_first_node(hw, tc_node, layer);
713
714 if (prev && prev != new_node) {
715 while (prev->sibling)
716 prev = prev->sibling;
717 prev->sibling = new_node;
718 }
719
720 if (i == 0)
721 *first_node_teid = teid;
722 }
723
724 devm_kfree(ice_hw_to_dev(hw), buf);
725 return status;
726}
727
728/**
729 * ice_sched_add_nodes_to_layer - Add nodes to a given layer
730 * @pi: port information structure
731 * @tc_node: pointer to TC node
732 * @parent: pointer to parent node
733 * @layer: layer number to add nodes
734 * @num_nodes: number of nodes to be added
735 * @first_node_teid: pointer to the first node teid
736 * @num_nodes_added: pointer to number of nodes added
737 *
738 * This function add nodes to a given layer.
739 */
740static enum ice_status
741ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
742 struct ice_sched_node *tc_node,
743 struct ice_sched_node *parent, u8 layer,
744 u16 num_nodes, u32 *first_node_teid,
745 u16 *num_nodes_added)
746{
747 u32 *first_teid_ptr = first_node_teid;
748 u16 new_num_nodes, max_child_nodes;
749 enum ice_status status = 0;
750 struct ice_hw *hw = pi->hw;
751 u16 num_added = 0;
752 u32 temp;
753
754 if (!num_nodes)
755 return status;
756
757 if (!parent || layer < hw->sw_entry_point_layer)
758 return ICE_ERR_PARAM;
759
760 *num_nodes_added = 0;
761
762 /* max children per node per layer */
763 max_child_nodes =
764 le16_to_cpu(hw->layer_info[parent->tx_sched_layer].max_children);
765
766 /* current number of children + required nodes exceed max children ? */
767 if ((parent->num_children + num_nodes) > max_child_nodes) {
768 /* Fail if the parent is a TC node */
769 if (parent == tc_node)
770 return ICE_ERR_CFG;
771
772 /* utilize all the spaces if the parent is not full */
773 if (parent->num_children < max_child_nodes) {
774 new_num_nodes = max_child_nodes - parent->num_children;
775 /* this recursion is intentional, and wouldn't
776 * go more than 2 calls
777 */
778 status = ice_sched_add_nodes_to_layer(pi, tc_node,
779 parent, layer,
780 new_num_nodes,
781 first_node_teid,
782 &num_added);
783 if (status)
784 return status;
785
786 *num_nodes_added += num_added;
787 }
788 /* Don't modify the first node teid memory if the first node was
789 * added already in the above call. Instead send some temp
790 * memory for all other recursive calls.
791 */
792 if (num_added)
793 first_teid_ptr = &temp;
794
795 new_num_nodes = num_nodes - num_added;
796
797 /* This parent is full, try the next sibling */
798 parent = parent->sibling;
799
800 /* this recursion is intentional, for 1024 queues
801 * per VSI, it goes max of 16 iterations.
802 * 1024 / 8 = 128 layer 8 nodes
803 * 128 /8 = 16 (add 8 nodes per iteration)
804 */
805 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,
806 layer, new_num_nodes,
807 first_teid_ptr,
808 &num_added);
809 *num_nodes_added += num_added;
810 return status;
811 }
812
813 status = ice_sched_add_elems(pi, tc_node, parent, layer, num_nodes,
814 num_nodes_added, first_node_teid);
815 return status;
816}
817
818/**
466 * ice_sched_get_qgrp_layer - get the current queue group layer number 819 * ice_sched_get_qgrp_layer - get the current queue group layer number
467 * @hw: pointer to the hw struct 820 * @hw: pointer to the hw struct
468 * 821 *
@@ -475,6 +828,101 @@ static u8 ice_sched_get_qgrp_layer(struct ice_hw *hw)
475} 828}
476 829
477/** 830/**
831 * ice_sched_get_vsi_layer - get the current VSI layer number
832 * @hw: pointer to the hw struct
833 *
834 * This function returns the current VSI layer number
835 */
836static u8 ice_sched_get_vsi_layer(struct ice_hw *hw)
837{
838 /* Num Layers VSI layer
839 * 9 6
840 * 7 4
841 * 5 or less sw_entry_point_layer
842 */
843 /* calculate the vsi layer based on number of layers. */
844 if (hw->num_tx_sched_layers > ICE_VSI_LAYER_OFFSET + 1) {
845 u8 layer = hw->num_tx_sched_layers - ICE_VSI_LAYER_OFFSET;
846
847 if (layer > hw->sw_entry_point_layer)
848 return layer;
849 }
850 return hw->sw_entry_point_layer;
851}
852
853/**
854 * ice_sched_get_num_nodes_per_layer - Get the total number of nodes per layer
855 * @pi: pointer to the port info struct
856 * @layer: layer number
857 *
858 * This function calculates the number of nodes present in the scheduler tree
859 * including all the branches for a given layer
860 */
861static u16
862ice_sched_get_num_nodes_per_layer(struct ice_port_info *pi, u8 layer)
863{
864 struct ice_hw *hw;
865 u16 num_nodes = 0;
866 u8 i;
867
868 if (!pi)
869 return num_nodes;
870
871 hw = pi->hw;
872
873 /* Calculate the number of nodes for all TCs */
874 for (i = 0; i < pi->root->num_children; i++) {
875 struct ice_sched_node *tc_node, *node;
876
877 tc_node = pi->root->children[i];
878
879 /* Get the first node */
880 node = ice_sched_get_first_node(hw, tc_node, layer);
881 if (!node)
882 continue;
883
884 /* count the siblings */
885 while (node) {
886 num_nodes++;
887 node = node->sibling;
888 }
889 }
890
891 return num_nodes;
892}
893
894/**
895 * ice_sched_val_max_nodes - check max number of nodes reached or not
896 * @pi: port information structure
897 * @new_num_nodes_per_layer: pointer to the new number of nodes array
898 *
899 * This function checks whether the scheduler tree layers have enough space to
900 * add new nodes
901 */
902static enum ice_status
903ice_sched_validate_for_max_nodes(struct ice_port_info *pi,
904 u16 *new_num_nodes_per_layer)
905{
906 struct ice_hw *hw = pi->hw;
907 u8 i, qg_layer;
908 u16 num_nodes;
909
910 qg_layer = ice_sched_get_qgrp_layer(hw);
911
912 /* walk through all the layers from SW entry point to qgroup layer */
913 for (i = hw->sw_entry_point_layer; i <= qg_layer; i++) {
914 num_nodes = ice_sched_get_num_nodes_per_layer(pi, i);
915 if (num_nodes + new_num_nodes_per_layer[i] >
916 le16_to_cpu(hw->layer_info[i].max_pf_nodes)) {
917 ice_debug(hw, ICE_DBG_SCHED,
918 "max nodes reached for layer = %d\n", i);
919 return ICE_ERR_CFG;
920 }
921 }
922 return 0;
923}
924
925/**
478 * ice_rm_dflt_leaf_node - remove the default leaf node in the tree 926 * ice_rm_dflt_leaf_node - remove the default leaf node in the tree
479 * @pi: port information structure 927 * @pi: port information structure
480 * 928 *
@@ -516,6 +964,7 @@ ice_sched_rm_dflt_nodes(struct ice_port_info *pi)
516 struct ice_sched_node *node; 964 struct ice_sched_node *node;
517 965
518 ice_rm_dflt_leaf_node(pi); 966 ice_rm_dflt_leaf_node(pi);
967
519 /* remove the default nodes except TC and root nodes */ 968 /* remove the default nodes except TC and root nodes */
520 node = pi->root; 969 node = pi->root;
521 while (node) { 970 while (node) {
@@ -525,6 +974,7 @@ ice_sched_rm_dflt_nodes(struct ice_port_info *pi)
525 ice_free_sched_node(pi, node); 974 ice_free_sched_node(pi, node);
526 break; 975 break;
527 } 976 }
977
528 if (!node->num_children) 978 if (!node->num_children)
529 break; 979 break;
530 node = node->children[0]; 980 node = node->children[0];
@@ -720,8 +1170,10 @@ ice_sched_find_node_in_subtree(struct ice_hw *hw, struct ice_sched_node *base,
720 1170
721 if (node == child) 1171 if (node == child)
722 return true; 1172 return true;
1173
723 if (child->tx_sched_layer > node->tx_sched_layer) 1174 if (child->tx_sched_layer > node->tx_sched_layer)
724 return false; 1175 return false;
1176
725 /* this recursion is intentional, and wouldn't 1177 /* this recursion is intentional, and wouldn't
726 * go more than 8 calls 1178 * go more than 8 calls
727 */ 1179 */
@@ -751,13 +1203,17 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
751 1203
752 qgrp_layer = ice_sched_get_qgrp_layer(pi->hw); 1204 qgrp_layer = ice_sched_get_qgrp_layer(pi->hw);
753 max_children = le16_to_cpu(pi->hw->layer_info[qgrp_layer].max_children); 1205 max_children = le16_to_cpu(pi->hw->layer_info[qgrp_layer].max_children);
1206
754 list_elem = ice_sched_get_vsi_info_entry(pi, vsi_id); 1207 list_elem = ice_sched_get_vsi_info_entry(pi, vsi_id);
755 if (!list_elem) 1208 if (!list_elem)
756 goto lan_q_exit; 1209 goto lan_q_exit;
1210
757 vsi_node = list_elem->vsi_node[tc]; 1211 vsi_node = list_elem->vsi_node[tc];
1212
758 /* validate invalid VSI id */ 1213 /* validate invalid VSI id */
759 if (!vsi_node) 1214 if (!vsi_node)
760 goto lan_q_exit; 1215 goto lan_q_exit;
1216
761 /* get the first q group node from VSI sub-tree */ 1217 /* get the first q group node from VSI sub-tree */
762 qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer); 1218 qgrp_node = ice_sched_get_first_node(pi->hw, vsi_node, qgrp_layer);
763 while (qgrp_node) { 1219 while (qgrp_node) {
@@ -768,6 +1224,436 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_id, u8 tc,
768 break; 1224 break;
769 qgrp_node = qgrp_node->sibling; 1225 qgrp_node = qgrp_node->sibling;
770 } 1226 }
1227
771lan_q_exit: 1228lan_q_exit:
772 return qgrp_node; 1229 return qgrp_node;
773} 1230}
1231
1232/**
1233 * ice_sched_get_vsi_node - Get a VSI node based on VSI id
1234 * @hw: pointer to the hw struct
1235 * @tc_node: pointer to the TC node
1236 * @vsi_id: VSI id
1237 *
1238 * This function retrieves a VSI node for a given VSI id from a given
1239 * TC branch
1240 */
1241static struct ice_sched_node *
1242ice_sched_get_vsi_node(struct ice_hw *hw, struct ice_sched_node *tc_node,
1243 u16 vsi_id)
1244{
1245 struct ice_sched_node *node;
1246 u8 vsi_layer;
1247
1248 vsi_layer = ice_sched_get_vsi_layer(hw);
1249 node = ice_sched_get_first_node(hw, tc_node, vsi_layer);
1250
1251 /* Check whether it already exists */
1252 while (node) {
1253 if (node->vsi_id == vsi_id)
1254 return node;
1255 node = node->sibling;
1256 }
1257
1258 return node;
1259}
1260
1261/**
1262 * ice_sched_calc_vsi_child_nodes - calculate number of VSI child nodes
1263 * @hw: pointer to the hw struct
1264 * @num_qs: number of queues
1265 * @num_nodes: num nodes array
1266 *
1267 * This function calculates the number of VSI child nodes based on the
1268 * number of queues.
1269 */
1270static void
1271ice_sched_calc_vsi_child_nodes(struct ice_hw *hw, u16 num_qs, u16 *num_nodes)
1272{
1273 u16 num = num_qs;
1274 u8 i, qgl, vsil;
1275
1276 qgl = ice_sched_get_qgrp_layer(hw);
1277 vsil = ice_sched_get_vsi_layer(hw);
1278
1279 /* calculate num nodes from q group to VSI layer */
1280 for (i = qgl; i > vsil; i--) {
1281 u16 max_children = le16_to_cpu(hw->layer_info[i].max_children);
1282
1283 /* round to the next integer if there is a remainder */
1284 num = DIV_ROUND_UP(num, max_children);
1285
1286 /* need at least one node */
1287 num_nodes[i] = num ? num : 1;
1288 }
1289}
1290
1291/**
1292 * ice_sched_add_vsi_child_nodes - add VSI child nodes to tree
1293 * @pi: port information structure
1294 * @vsi_id: VSI id
1295 * @tc_node: pointer to the TC node
1296 * @num_nodes: pointer to the num nodes that needs to be added per layer
1297 * @owner: node owner (lan or rdma)
1298 *
1299 * This function adds the VSI child nodes to tree. It gets called for
1300 * lan and rdma separately.
1301 */
1302static enum ice_status
1303ice_sched_add_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_id,
1304 struct ice_sched_node *tc_node, u16 *num_nodes,
1305 u8 owner)
1306{
1307 struct ice_sched_node *parent, *node;
1308 struct ice_hw *hw = pi->hw;
1309 enum ice_status status;
1310 u32 first_node_teid;
1311 u16 num_added = 0;
1312 u8 i, qgl, vsil;
1313
1314 status = ice_sched_validate_for_max_nodes(pi, num_nodes);
1315 if (status)
1316 return status;
1317
1318 qgl = ice_sched_get_qgrp_layer(hw);
1319 vsil = ice_sched_get_vsi_layer(hw);
1320 parent = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
1321 for (i = vsil + 1; i <= qgl; i++) {
1322 if (!parent)
1323 return ICE_ERR_CFG;
1324 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent, i,
1325 num_nodes[i],
1326 &first_node_teid,
1327 &num_added);
1328 if (status || num_nodes[i] != num_added)
1329 return ICE_ERR_CFG;
1330
1331 /* The newly added node can be a new parent for the next
1332 * layer nodes
1333 */
1334 if (num_added) {
1335 parent = ice_sched_find_node_by_teid(tc_node,
1336 first_node_teid);
1337 node = parent;
1338 while (node) {
1339 node->owner = owner;
1340 node = node->sibling;
1341 }
1342 } else {
1343 parent = parent->children[0];
1344 }
1345 }
1346
1347 return 0;
1348}
1349
1350/**
1351 * ice_sched_rm_vsi_child_nodes - remove VSI child nodes from the tree
1352 * @pi: port information structure
1353 * @vsi_node: pointer to the VSI node
1354 * @num_nodes: pointer to the num nodes that needs to be removed per layer
1355 * @owner: node owner (lan or rdma)
1356 *
1357 * This function removes the VSI child nodes from the tree. It gets called for
1358 * lan and rdma separately.
1359 */
1360static void
1361ice_sched_rm_vsi_child_nodes(struct ice_port_info *pi,
1362 struct ice_sched_node *vsi_node, u16 *num_nodes,
1363 u8 owner)
1364{
1365 struct ice_sched_node *node, *next;
1366 u8 i, qgl, vsil;
1367 u16 num;
1368
1369 qgl = ice_sched_get_qgrp_layer(pi->hw);
1370 vsil = ice_sched_get_vsi_layer(pi->hw);
1371
1372 for (i = qgl; i > vsil; i--) {
1373 num = num_nodes[i];
1374 node = ice_sched_get_first_node(pi->hw, vsi_node, i);
1375 while (node && num) {
1376 next = node->sibling;
1377 if (node->owner == owner && !node->num_children) {
1378 ice_free_sched_node(pi, node);
1379 num--;
1380 }
1381 node = next;
1382 }
1383 }
1384}
1385
1386/**
1387 * ice_sched_calc_vsi_support_nodes - calculate number of VSI support nodes
1388 * @hw: pointer to the hw struct
1389 * @tc_node: pointer to TC node
1390 * @num_nodes: pointer to num nodes array
1391 *
1392 * This function calculates the number of supported nodes needed to add this
1393 * VSI into tx tree including the VSI, parent and intermediate nodes in below
1394 * layers
1395 */
1396static void
1397ice_sched_calc_vsi_support_nodes(struct ice_hw *hw,
1398 struct ice_sched_node *tc_node, u16 *num_nodes)
1399{
1400 struct ice_sched_node *node;
1401 u16 max_child;
1402 u8 i, vsil;
1403
1404 vsil = ice_sched_get_vsi_layer(hw);
1405 for (i = vsil; i >= hw->sw_entry_point_layer; i--)
1406 /* Add intermediate nodes if TC has no children and
1407 * need at least one node for VSI
1408 */
1409 if (!tc_node->num_children || i == vsil) {
1410 num_nodes[i]++;
1411 } else {
1412 /* If intermediate nodes are reached max children
1413 * then add a new one.
1414 */
1415 node = ice_sched_get_first_node(hw, tc_node, i);
1416 max_child = le16_to_cpu(hw->layer_info[i].max_children);
1417
1418 /* scan all the siblings */
1419 while (node) {
1420 if (node->num_children < max_child)
1421 break;
1422 node = node->sibling;
1423 }
1424
1425 /* all the nodes are full, allocate a new one */
1426 if (!node)
1427 num_nodes[i]++;
1428 }
1429}
1430
1431/**
1432 * ice_sched_add_vsi_support_nodes - add VSI supported nodes into tx tree
1433 * @pi: port information structure
1434 * @vsi_id: VSI Id
1435 * @tc_node: pointer to TC node
1436 * @num_nodes: pointer to num nodes array
1437 *
1438 * This function adds the VSI supported nodes into tx tree including the
1439 * VSI, its parent and intermediate nodes in below layers
1440 */
1441static enum ice_status
1442ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_id,
1443 struct ice_sched_node *tc_node, u16 *num_nodes)
1444{
1445 struct ice_sched_node *parent = tc_node;
1446 enum ice_status status;
1447 u32 first_node_teid;
1448 u16 num_added = 0;
1449 u8 i, vsil;
1450
1451 if (!pi)
1452 return ICE_ERR_PARAM;
1453
1454 status = ice_sched_validate_for_max_nodes(pi, num_nodes);
1455 if (status)
1456 return status;
1457
1458 vsil = ice_sched_get_vsi_layer(pi->hw);
1459 for (i = pi->hw->sw_entry_point_layer; i <= vsil; i++) {
1460 status = ice_sched_add_nodes_to_layer(pi, tc_node, parent,
1461 i, num_nodes[i],
1462 &first_node_teid,
1463 &num_added);
1464 if (status || num_nodes[i] != num_added)
1465 return ICE_ERR_CFG;
1466
1467 /* The newly added node can be a new parent for the next
1468 * layer nodes
1469 */
1470 if (num_added)
1471 parent = ice_sched_find_node_by_teid(tc_node,
1472 first_node_teid);
1473 else
1474 parent = parent->children[0];
1475
1476 if (!parent)
1477 return ICE_ERR_CFG;
1478
1479 if (i == vsil)
1480 parent->vsi_id = vsi_id;
1481 }
1482 return 0;
1483}
1484
1485/**
1486 * ice_sched_add_vsi_to_topo - add a new VSI into tree
1487 * @pi: port information structure
1488 * @vsi_id: VSI Id
1489 * @tc: TC number
1490 *
1491 * This function adds a new VSI into scheduler tree
1492 */
1493static enum ice_status
1494ice_sched_add_vsi_to_topo(struct ice_port_info *pi, u16 vsi_id, u8 tc)
1495{
1496 u16 num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
1497 struct ice_sched_node *tc_node;
1498 struct ice_hw *hw = pi->hw;
1499
1500 tc_node = ice_sched_get_tc_node(pi, tc);
1501 if (!tc_node)
1502 return ICE_ERR_PARAM;
1503
1504 /* calculate number of supported nodes needed for this VSI */
1505 ice_sched_calc_vsi_support_nodes(hw, tc_node, num_nodes);
1506
1507 /* add vsi supported nodes to tc subtree */
1508 return ice_sched_add_vsi_support_nodes(pi, vsi_id, tc_node, num_nodes);
1509}
1510
1511/**
1512 * ice_sched_update_vsi_child_nodes - update VSI child nodes
1513 * @pi: port information structure
1514 * @vsi_id: VSI Id
1515 * @tc: TC number
1516 * @new_numqs: new number of max queues
1517 * @owner: owner of this subtree
1518 *
1519 * This function updates the VSI child nodes based on the number of queues
1520 */
1521static enum ice_status
1522ice_sched_update_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_id, u8 tc,
1523 u16 new_numqs, u8 owner)
1524{
1525 u16 prev_num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
1526 u16 new_num_nodes[ICE_AQC_TOPO_MAX_LEVEL_NUM] = { 0 };
1527 struct ice_sched_node *vsi_node;
1528 struct ice_sched_node *tc_node;
1529 struct ice_sched_vsi_info *vsi;
1530 enum ice_status status = 0;
1531 struct ice_hw *hw = pi->hw;
1532 u16 prev_numqs;
1533 u8 i;
1534
1535 tc_node = ice_sched_get_tc_node(pi, tc);
1536 if (!tc_node)
1537 return ICE_ERR_CFG;
1538
1539 vsi_node = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
1540 if (!vsi_node)
1541 return ICE_ERR_CFG;
1542
1543 vsi = ice_sched_get_vsi_info_entry(pi, vsi_id);
1544 if (!vsi)
1545 return ICE_ERR_CFG;
1546
1547 if (owner == ICE_SCHED_NODE_OWNER_LAN)
1548 prev_numqs = vsi->max_lanq[tc];
1549 else
1550 return ICE_ERR_PARAM;
1551
1552 /* num queues are not changed */
1553 if (prev_numqs == new_numqs)
1554 return status;
1555
1556 /* calculate number of nodes based on prev/new number of qs */
1557 if (prev_numqs)
1558 ice_sched_calc_vsi_child_nodes(hw, prev_numqs, prev_num_nodes);
1559
1560 if (new_numqs)
1561 ice_sched_calc_vsi_child_nodes(hw, new_numqs, new_num_nodes);
1562
1563 if (prev_numqs > new_numqs) {
1564 for (i = 0; i < ICE_AQC_TOPO_MAX_LEVEL_NUM; i++)
1565 new_num_nodes[i] = prev_num_nodes[i] - new_num_nodes[i];
1566
1567 ice_sched_rm_vsi_child_nodes(pi, vsi_node, new_num_nodes,
1568 owner);
1569 } else {
1570 for (i = 0; i < ICE_AQC_TOPO_MAX_LEVEL_NUM; i++)
1571 new_num_nodes[i] -= prev_num_nodes[i];
1572
1573 status = ice_sched_add_vsi_child_nodes(pi, vsi_id, tc_node,
1574 new_num_nodes, owner);
1575 if (status)
1576 return status;
1577 }
1578
1579 if (owner == ICE_SCHED_NODE_OWNER_LAN)
1580 vsi->max_lanq[tc] = new_numqs;
1581
1582 return status;
1583}
1584
1585/**
1586 * ice_sched_cfg_vsi - configure the new/exisiting VSI
1587 * @pi: port information structure
1588 * @vsi_id: VSI Id
1589 * @tc: TC number
1590 * @maxqs: max number of queues
1591 * @owner: lan or rdma
1592 * @enable: TC enabled or disabled
1593 *
1594 * This function adds/updates VSI nodes based on the number of queues. If TC is
1595 * enabled and VSI is in suspended state then resume the VSI back. If TC is
1596 * disabled then suspend the VSI if it is not already.
1597 */
1598enum ice_status
1599ice_sched_cfg_vsi(struct ice_port_info *pi, u16 vsi_id, u8 tc, u16 maxqs,
1600 u8 owner, bool enable)
1601{
1602 struct ice_sched_node *vsi_node, *tc_node;
1603 struct ice_sched_vsi_info *vsi;
1604 enum ice_status status = 0;
1605 struct ice_hw *hw = pi->hw;
1606
1607 tc_node = ice_sched_get_tc_node(pi, tc);
1608 if (!tc_node)
1609 return ICE_ERR_PARAM;
1610
1611 vsi = ice_sched_get_vsi_info_entry(pi, vsi_id);
1612 if (!vsi)
1613 vsi = ice_sched_create_vsi_info_entry(pi, vsi_id);
1614 if (!vsi)
1615 return ICE_ERR_NO_MEMORY;
1616
1617 vsi_node = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
1618
1619 /* suspend the VSI if tc is not enabled */
1620 if (!enable) {
1621 if (vsi_node && vsi_node->in_use) {
1622 u32 teid = le32_to_cpu(vsi_node->info.node_teid);
1623
1624 status = ice_sched_suspend_resume_elems(hw, 1, &teid,
1625 true);
1626 if (!status)
1627 vsi_node->in_use = false;
1628 }
1629 return status;
1630 }
1631
1632 /* TC is enabled, if it is a new VSI then add it to the tree */
1633 if (!vsi_node) {
1634 status = ice_sched_add_vsi_to_topo(pi, vsi_id, tc);
1635 if (status)
1636 return status;
1637 vsi_node = ice_sched_get_vsi_node(hw, tc_node, vsi_id);
1638 if (!vsi_node)
1639 return ICE_ERR_CFG;
1640 vsi->vsi_node[tc] = vsi_node;
1641 vsi_node->in_use = true;
1642 }
1643
1644 /* update the VSI child nodes */
1645 status = ice_sched_update_vsi_child_nodes(pi, vsi_id, tc, maxqs, owner);
1646 if (status)
1647 return status;
1648
1649 /* TC is enabled, resume the VSI if it is in the suspend state */
1650 if (!vsi_node->in_use) {
1651 u32 teid = le32_to_cpu(vsi_node->info.node_teid);
1652
1653 status = ice_sched_suspend_resume_elems(hw, 1, &teid, false);
1654 if (!status)
1655 vsi_node->in_use = true;
1656 }
1657
1658 return status;
1659}