@@ -84,6 +84,27 @@ ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid)
84
84
return NULL ;
85
85
}
86
86
87
+ /**
88
+ * ice_sched_find_next_vsi_node - find the next node for a given VSI
89
+ * @vsi_node: VSI support node to start search with
90
+ *
91
+ * Return: Next VSI support node, or NULL.
92
+ *
93
+ * The function returns a pointer to the next node from the VSI layer
94
+ * assigned to the given VSI, or NULL if there is no such a node.
95
+ */
96
+ static struct ice_sched_node *
97
+ ice_sched_find_next_vsi_node (struct ice_sched_node * vsi_node )
98
+ {
99
+ unsigned int vsi_handle = vsi_node -> vsi_handle ;
100
+
101
+ while ((vsi_node = vsi_node -> sibling ) != NULL )
102
+ if (vsi_node -> vsi_handle == vsi_handle )
103
+ break ;
104
+
105
+ return vsi_node ;
106
+ }
107
+
87
108
/**
88
109
* ice_aqc_send_sched_elem_cmd - send scheduling elements cmd
89
110
* @hw: pointer to the HW struct
@@ -1084,8 +1105,10 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
1084
1105
if (parent -> num_children < max_child_nodes ) {
1085
1106
new_num_nodes = max_child_nodes - parent -> num_children ;
1086
1107
} else {
1087
- /* This parent is full, try the next sibling */
1088
- parent = parent -> sibling ;
1108
+ /* This parent is full,
1109
+ * try the next available sibling.
1110
+ */
1111
+ parent = ice_sched_find_next_vsi_node (parent );
1089
1112
/* Don't modify the first node TEID memory if the
1090
1113
* first node was added already in the above call.
1091
1114
* Instead send some temp memory for all other
@@ -1528,12 +1551,23 @@ ice_sched_get_free_qparent(struct ice_port_info *pi, u16 vsi_handle, u8 tc,
1528
1551
/* get the first queue group node from VSI sub-tree */
1529
1552
qgrp_node = ice_sched_get_first_node (pi , vsi_node , qgrp_layer );
1530
1553
while (qgrp_node ) {
1554
+ struct ice_sched_node * next_vsi_node ;
1555
+
1531
1556
/* make sure the qgroup node is part of the VSI subtree */
1532
1557
if (ice_sched_find_node_in_subtree (pi -> hw , vsi_node , qgrp_node ))
1533
1558
if (qgrp_node -> num_children < max_children &&
1534
1559
qgrp_node -> owner == owner )
1535
1560
break ;
1536
1561
qgrp_node = qgrp_node -> sibling ;
1562
+ if (qgrp_node )
1563
+ continue ;
1564
+
1565
+ next_vsi_node = ice_sched_find_next_vsi_node (vsi_node );
1566
+ if (!next_vsi_node )
1567
+ break ;
1568
+
1569
+ vsi_node = next_vsi_node ;
1570
+ qgrp_node = ice_sched_get_first_node (pi , vsi_node , qgrp_layer );
1537
1571
}
1538
1572
1539
1573
/* Select the best queue group */
@@ -1604,16 +1638,16 @@ ice_sched_get_agg_node(struct ice_port_info *pi, struct ice_sched_node *tc_node,
1604
1638
/**
1605
1639
* ice_sched_calc_vsi_child_nodes - calculate number of VSI child nodes
1606
1640
* @hw: pointer to the HW struct
1607
- * @num_qs : number of queues
1641
+ * @num_new_qs : number of new queues that will be added to the tree
1608
1642
* @num_nodes: num nodes array
1609
1643
*
1610
1644
* This function calculates the number of VSI child nodes based on the
1611
1645
* number of queues.
1612
1646
*/
1613
1647
static void
1614
- ice_sched_calc_vsi_child_nodes (struct ice_hw * hw , u16 num_qs , u16 * num_nodes )
1648
+ ice_sched_calc_vsi_child_nodes (struct ice_hw * hw , u16 num_new_qs , u16 * num_nodes )
1615
1649
{
1616
- u16 num = num_qs ;
1650
+ u16 num = num_new_qs ;
1617
1651
u8 i , qgl , vsil ;
1618
1652
1619
1653
qgl = ice_sched_get_qgrp_layer (hw );
@@ -1779,7 +1813,11 @@ ice_sched_add_vsi_support_nodes(struct ice_port_info *pi, u16 vsi_handle,
1779
1813
if (!parent )
1780
1814
return - EIO ;
1781
1815
1782
- if (i == vsil )
1816
+ /* Do not modify the VSI handle for already existing VSI nodes,
1817
+ * (if no new VSI node was added to the tree).
1818
+ * Assign the VSI handle only to newly added VSI nodes.
1819
+ */
1820
+ if (i == vsil && num_added )
1783
1821
parent -> vsi_handle = vsi_handle ;
1784
1822
}
1785
1823
@@ -1812,6 +1850,41 @@ ice_sched_add_vsi_to_topo(struct ice_port_info *pi, u16 vsi_handle, u8 tc)
1812
1850
num_nodes );
1813
1851
}
1814
1852
1853
+ /**
1854
+ * ice_sched_recalc_vsi_support_nodes - recalculate VSI support nodes count
1855
+ * @hw: pointer to the HW struct
1856
+ * @vsi_node: pointer to the leftmost VSI node that needs to be extended
1857
+ * @new_numqs: new number of queues that has to be handled by the VSI
1858
+ * @new_num_nodes: pointer to nodes count table to modify the VSI layer entry
1859
+ *
1860
+ * This function recalculates the number of supported nodes that need to
1861
+ * be added after adding more Tx queues for a given VSI.
1862
+ * The number of new VSI support nodes that shall be added will be saved
1863
+ * to the @new_num_nodes table for the VSI layer.
1864
+ */
1865
+ static void
1866
+ ice_sched_recalc_vsi_support_nodes (struct ice_hw * hw ,
1867
+ struct ice_sched_node * vsi_node ,
1868
+ unsigned int new_numqs , u16 * new_num_nodes )
1869
+ {
1870
+ u32 vsi_nodes_cnt = 1 ;
1871
+ u32 max_queue_cnt = 1 ;
1872
+ u32 qgl , vsil ;
1873
+
1874
+ qgl = ice_sched_get_qgrp_layer (hw );
1875
+ vsil = ice_sched_get_vsi_layer (hw );
1876
+
1877
+ for (u32 i = vsil ; i <= qgl ; i ++ )
1878
+ max_queue_cnt *= hw -> max_children [i ];
1879
+
1880
+ while ((vsi_node = ice_sched_find_next_vsi_node (vsi_node )) != NULL )
1881
+ vsi_nodes_cnt ++ ;
1882
+
1883
+ if (new_numqs > (max_queue_cnt * vsi_nodes_cnt ))
1884
+ new_num_nodes [vsil ] = DIV_ROUND_UP (new_numqs , max_queue_cnt ) -
1885
+ vsi_nodes_cnt ;
1886
+ }
1887
+
1815
1888
/**
1816
1889
* ice_sched_update_vsi_child_nodes - update VSI child nodes
1817
1890
* @pi: port information structure
@@ -1863,15 +1936,25 @@ ice_sched_update_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_handle,
1863
1936
return status ;
1864
1937
}
1865
1938
1866
- if (new_numqs )
1867
- ice_sched_calc_vsi_child_nodes (hw , new_numqs , new_num_nodes );
1868
- /* Keep the max number of queue configuration all the time. Update the
1869
- * tree only if number of queues > previous number of queues. This may
1939
+ ice_sched_recalc_vsi_support_nodes (hw , vsi_node ,
1940
+ new_numqs , new_num_nodes );
1941
+ ice_sched_calc_vsi_child_nodes (hw , new_numqs - prev_numqs ,
1942
+ new_num_nodes );
1943
+
1944
+ /* Never decrease the number of queues in the tree. Update the tree
1945
+ * only if number of queues > previous number of queues. This may
1870
1946
* leave some extra nodes in the tree if number of queues < previous
1871
1947
* number but that wouldn't harm anything. Removing those extra nodes
1872
1948
* may complicate the code if those nodes are part of SRL or
1873
1949
* individually rate limited.
1950
+ * Also, add the required VSI support nodes if the existing ones cannot
1951
+ * handle the requested new number of queues.
1874
1952
*/
1953
+ status = ice_sched_add_vsi_support_nodes (pi , vsi_handle , tc_node ,
1954
+ new_num_nodes );
1955
+ if (status )
1956
+ return status ;
1957
+
1875
1958
status = ice_sched_add_vsi_child_nodes (pi , vsi_handle , tc_node ,
1876
1959
new_num_nodes , owner );
1877
1960
if (status )
@@ -2012,6 +2095,58 @@ static bool ice_sched_is_leaf_node_present(struct ice_sched_node *node)
2012
2095
return (node -> info .data .elem_type == ICE_AQC_ELEM_TYPE_LEAF );
2013
2096
}
2014
2097
2098
+ /**
2099
+ * ice_sched_rm_vsi_subtree - remove all nodes assigned to a given VSI
2100
+ * @pi: port information structure
2101
+ * @vsi_node: pointer to the leftmost node of the VSI to be removed
2102
+ * @owner: LAN or RDMA
2103
+ * @tc: TC number
2104
+ *
2105
+ * Return: Zero in case of success, or -EBUSY if the VSI has leaf nodes in TC.
2106
+ *
2107
+ * This function removes all the VSI support nodes associated with a given VSI
2108
+ * and its LAN or RDMA children nodes from the scheduler tree.
2109
+ */
2110
+ static int
2111
+ ice_sched_rm_vsi_subtree (struct ice_port_info * pi ,
2112
+ struct ice_sched_node * vsi_node , u8 owner , u8 tc )
2113
+ {
2114
+ u16 vsi_handle = vsi_node -> vsi_handle ;
2115
+ bool all_vsi_nodes_removed = true;
2116
+ int j = 0 ;
2117
+
2118
+ while (vsi_node ) {
2119
+ struct ice_sched_node * next_vsi_node ;
2120
+
2121
+ if (ice_sched_is_leaf_node_present (vsi_node )) {
2122
+ ice_debug (pi -> hw , ICE_DBG_SCHED , "VSI has leaf nodes in TC %d\n" , tc );
2123
+ return - EBUSY ;
2124
+ }
2125
+ while (j < vsi_node -> num_children ) {
2126
+ if (vsi_node -> children [j ]-> owner == owner )
2127
+ ice_free_sched_node (pi , vsi_node -> children [j ]);
2128
+ else
2129
+ j ++ ;
2130
+ }
2131
+
2132
+ next_vsi_node = ice_sched_find_next_vsi_node (vsi_node );
2133
+
2134
+ /* remove the VSI if it has no children */
2135
+ if (!vsi_node -> num_children )
2136
+ ice_free_sched_node (pi , vsi_node );
2137
+ else
2138
+ all_vsi_nodes_removed = false;
2139
+
2140
+ vsi_node = next_vsi_node ;
2141
+ }
2142
+
2143
+ /* clean up aggregator related VSI info if any */
2144
+ if (all_vsi_nodes_removed )
2145
+ ice_sched_rm_agg_vsi_info (pi , vsi_handle );
2146
+
2147
+ return 0 ;
2148
+ }
2149
+
2015
2150
/**
2016
2151
* ice_sched_rm_vsi_cfg - remove the VSI and its children nodes
2017
2152
* @pi: port information structure
@@ -2038,7 +2173,6 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
2038
2173
2039
2174
ice_for_each_traffic_class (i ) {
2040
2175
struct ice_sched_node * vsi_node , * tc_node ;
2041
- u8 j = 0 ;
2042
2176
2043
2177
tc_node = ice_sched_get_tc_node (pi , i );
2044
2178
if (!tc_node )
@@ -2048,31 +2182,12 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
2048
2182
if (!vsi_node )
2049
2183
continue ;
2050
2184
2051
- if (ice_sched_is_leaf_node_present (vsi_node )) {
2052
- ice_debug (pi -> hw , ICE_DBG_SCHED , "VSI has leaf nodes in TC %d\n" , i );
2053
- status = - EBUSY ;
2185
+ status = ice_sched_rm_vsi_subtree (pi , vsi_node , owner , i );
2186
+ if (status )
2054
2187
goto exit_sched_rm_vsi_cfg ;
2055
- }
2056
- while (j < vsi_node -> num_children ) {
2057
- if (vsi_node -> children [j ]-> owner == owner ) {
2058
- ice_free_sched_node (pi , vsi_node -> children [j ]);
2059
2188
2060
- /* reset the counter again since the num
2061
- * children will be updated after node removal
2062
- */
2063
- j = 0 ;
2064
- } else {
2065
- j ++ ;
2066
- }
2067
- }
2068
- /* remove the VSI if it has no children */
2069
- if (!vsi_node -> num_children ) {
2070
- ice_free_sched_node (pi , vsi_node );
2071
- vsi_ctx -> sched .vsi_node [i ] = NULL ;
2189
+ vsi_ctx -> sched .vsi_node [i ] = NULL ;
2072
2190
2073
- /* clean up aggregator related VSI info if any */
2074
- ice_sched_rm_agg_vsi_info (pi , vsi_handle );
2075
- }
2076
2191
if (owner == ICE_SCHED_NODE_OWNER_LAN )
2077
2192
vsi_ctx -> sched .max_lanq [i ] = 0 ;
2078
2193
else
0 commit comments