Skip to content

Commit 408da3a

Browse files
committed
Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue
Tony Nguyen says: ==================== Intel Wired LAN Driver Updates 2025-05-30 (ice, idpf) For ice: Michal resolves XDP issues related to Tx scheduler configuration with large number of Tx queues. Additional information: https://lore.kernel.org/intel-wired-lan/[email protected]/ For idpf: Brian Vazquez updates netif_subqueue_maybe_stop() condition check to prevent possible races. Emil shuts down virtchannel mailbox during reset to reduce timeout delays as it's unavailable during that time. * '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue: idpf: avoid mailbox timeout delays during reset idpf: fix a race in txq wakeup ice: fix rebuilding the Tx scheduler tree for large queue counts ice: create new Tx scheduler nodes for new queues only ice: fix Tx scheduler error handling in XDP callback ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 3382a1e + 9dc63d8 commit 408da3a

File tree

8 files changed

+218
-93
lines changed

8 files changed

+218
-93
lines changed

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,6 +2740,27 @@ void ice_map_xdp_rings(struct ice_vsi *vsi)
27402740
}
27412741
}
27422742

2743+
/**
2744+
* ice_unmap_xdp_rings - Unmap XDP rings from interrupt vectors
2745+
* @vsi: the VSI with XDP rings being unmapped
2746+
*/
2747+
static void ice_unmap_xdp_rings(struct ice_vsi *vsi)
2748+
{
2749+
int v_idx;
2750+
2751+
ice_for_each_q_vector(vsi, v_idx) {
2752+
struct ice_q_vector *q_vector = vsi->q_vectors[v_idx];
2753+
struct ice_tx_ring *ring;
2754+
2755+
ice_for_each_tx_ring(ring, q_vector->tx)
2756+
if (!ring->tx_buf || !ice_ring_is_xdp(ring))
2757+
break;
2758+
2759+
/* restore the value of last node prior to XDP setup */
2760+
q_vector->tx.tx_ring = ring;
2761+
}
2762+
}
2763+
27432764
/**
27442765
* ice_prepare_xdp_rings - Allocate, configure and setup Tx rings for XDP
27452766
* @vsi: VSI to bring up Tx rings used by XDP
@@ -2803,7 +2824,7 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog,
28032824
if (status) {
28042825
dev_err(dev, "Failed VSI LAN queue config for XDP, error: %d\n",
28052826
status);
2806-
goto clear_xdp_rings;
2827+
goto unmap_xdp_rings;
28072828
}
28082829

28092830
/* assign the prog only when it's not already present on VSI;
@@ -2819,6 +2840,8 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog,
28192840
ice_vsi_assign_bpf_prog(vsi, prog);
28202841

28212842
return 0;
2843+
unmap_xdp_rings:
2844+
ice_unmap_xdp_rings(vsi);
28222845
clear_xdp_rings:
28232846
ice_for_each_xdp_txq(vsi, i)
28242847
if (vsi->xdp_rings[i]) {
@@ -2835,6 +2858,8 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog,
28352858
mutex_unlock(&pf->avail_q_mutex);
28362859

28372860
devm_kfree(dev, vsi->xdp_rings);
2861+
vsi->xdp_rings = NULL;
2862+
28382863
return -ENOMEM;
28392864
}
28402865

@@ -2850,25 +2875,15 @@ int ice_destroy_xdp_rings(struct ice_vsi *vsi, enum ice_xdp_cfg cfg_type)
28502875
{
28512876
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
28522877
struct ice_pf *pf = vsi->back;
2853-
int i, v_idx;
2878+
int i;
28542879

28552880
/* q_vectors are freed in reset path so there's no point in detaching
28562881
* rings
28572882
*/
28582883
if (cfg_type == ICE_XDP_CFG_PART)
28592884
goto free_qmap;
28602885

2861-
ice_for_each_q_vector(vsi, v_idx) {
2862-
struct ice_q_vector *q_vector = vsi->q_vectors[v_idx];
2863-
struct ice_tx_ring *ring;
2864-
2865-
ice_for_each_tx_ring(ring, q_vector->tx)
2866-
if (!ring->tx_buf || !ice_ring_is_xdp(ring))
2867-
break;
2868-
2869-
/* restore the value of last node prior to XDP setup */
2870-
q_vector->tx.tx_ring = ring;
2871-
}
2886+
ice_unmap_xdp_rings(vsi);
28722887

28732888
free_qmap:
28742889
mutex_lock(&pf->avail_q_mutex);
@@ -3013,11 +3028,14 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
30133028
xdp_ring_err = ice_vsi_determine_xdp_res(vsi);
30143029
if (xdp_ring_err) {
30153030
NL_SET_ERR_MSG_MOD(extack, "Not enough Tx resources for XDP");
3031+
goto resume_if;
30163032
} else {
30173033
xdp_ring_err = ice_prepare_xdp_rings(vsi, prog,
30183034
ICE_XDP_CFG_FULL);
3019-
if (xdp_ring_err)
3035+
if (xdp_ring_err) {
30203036
NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed");
3037+
goto resume_if;
3038+
}
30213039
}
30223040
xdp_features_set_redirect_target(vsi->netdev, true);
30233041
/* reallocate Rx queues that are used for zero-copy */
@@ -3035,6 +3053,7 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
30353053
NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed");
30363054
}
30373055

3056+
resume_if:
30383057
if (if_running)
30393058
ret = ice_up(vsi);
30403059

drivers/net/ethernet/intel/ice/ice_sched.c

Lines changed: 148 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,27 @@ ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid)
8484
return NULL;
8585
}
8686

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+
87108
/**
88109
* ice_aqc_send_sched_elem_cmd - send scheduling elements cmd
89110
* @hw: pointer to the HW struct
@@ -1084,8 +1105,10 @@ ice_sched_add_nodes_to_layer(struct ice_port_info *pi,
10841105
if (parent->num_children < max_child_nodes) {
10851106
new_num_nodes = max_child_nodes - parent->num_children;
10861107
} 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);
10891112
/* Don't modify the first node TEID memory if the
10901113
* first node was added already in the above call.
10911114
* 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,
15281551
/* get the first queue group node from VSI sub-tree */
15291552
qgrp_node = ice_sched_get_first_node(pi, vsi_node, qgrp_layer);
15301553
while (qgrp_node) {
1554+
struct ice_sched_node *next_vsi_node;
1555+
15311556
/* make sure the qgroup node is part of the VSI subtree */
15321557
if (ice_sched_find_node_in_subtree(pi->hw, vsi_node, qgrp_node))
15331558
if (qgrp_node->num_children < max_children &&
15341559
qgrp_node->owner == owner)
15351560
break;
15361561
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);
15371571
}
15381572

15391573
/* 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,
16041638
/**
16051639
* ice_sched_calc_vsi_child_nodes - calculate number of VSI child nodes
16061640
* @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
16081642
* @num_nodes: num nodes array
16091643
*
16101644
* This function calculates the number of VSI child nodes based on the
16111645
* number of queues.
16121646
*/
16131647
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)
16151649
{
1616-
u16 num = num_qs;
1650+
u16 num = num_new_qs;
16171651
u8 i, qgl, vsil;
16181652

16191653
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,
17791813
if (!parent)
17801814
return -EIO;
17811815

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)
17831821
parent->vsi_handle = vsi_handle;
17841822
}
17851823

@@ -1812,6 +1850,41 @@ ice_sched_add_vsi_to_topo(struct ice_port_info *pi, u16 vsi_handle, u8 tc)
18121850
num_nodes);
18131851
}
18141852

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+
18151888
/**
18161889
* ice_sched_update_vsi_child_nodes - update VSI child nodes
18171890
* @pi: port information structure
@@ -1863,15 +1936,25 @@ ice_sched_update_vsi_child_nodes(struct ice_port_info *pi, u16 vsi_handle,
18631936
return status;
18641937
}
18651938

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
18701946
* leave some extra nodes in the tree if number of queues < previous
18711947
* number but that wouldn't harm anything. Removing those extra nodes
18721948
* may complicate the code if those nodes are part of SRL or
18731949
* individually rate limited.
1950+
* Also, add the required VSI support nodes if the existing ones cannot
1951+
* handle the requested new number of queues.
18741952
*/
1953+
status = ice_sched_add_vsi_support_nodes(pi, vsi_handle, tc_node,
1954+
new_num_nodes);
1955+
if (status)
1956+
return status;
1957+
18751958
status = ice_sched_add_vsi_child_nodes(pi, vsi_handle, tc_node,
18761959
new_num_nodes, owner);
18771960
if (status)
@@ -2012,6 +2095,58 @@ static bool ice_sched_is_leaf_node_present(struct ice_sched_node *node)
20122095
return (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF);
20132096
}
20142097

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+
20152150
/**
20162151
* ice_sched_rm_vsi_cfg - remove the VSI and its children nodes
20172152
* @pi: port information structure
@@ -2038,7 +2173,6 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
20382173

20392174
ice_for_each_traffic_class(i) {
20402175
struct ice_sched_node *vsi_node, *tc_node;
2041-
u8 j = 0;
20422176

20432177
tc_node = ice_sched_get_tc_node(pi, i);
20442178
if (!tc_node)
@@ -2048,31 +2182,12 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner)
20482182
if (!vsi_node)
20492183
continue;
20502184

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)
20542187
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]);
20592188

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;
20722190

2073-
/* clean up aggregator related VSI info if any */
2074-
ice_sched_rm_agg_vsi_info(pi, vsi_handle);
2075-
}
20762191
if (owner == ICE_SCHED_NODE_OWNER_LAN)
20772192
vsi_ctx->sched.max_lanq[i] = 0;
20782193
else

0 commit comments

Comments
 (0)