Merge branch '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2026-09-08 (idpf, ice)

For idpf:
Myeonghun Pak adds calls to disable DIM work and PTM to allow for proper
cleanup.

Josh adds check, and adjustment, for VLAN headers when processing RSC
packets.

For ice:
Jake adds call to xa_destroy for xarray sched_node_ids; also moving it
from port_info struct to ice_hw to simplify its lifecycle management.

Jakub Kicinski stores trace event data as scalars instead of
dereferencing pointers in TP_printk(), preventing use-after-free issues
during event printing and eliminating double-dereference warnings.

* '200GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue:
  eth: ice: don't dereference pointers from TP_printk()
  ice: add missing xa_destroy for sched_node_ids
  idpf: account for VLAN header when parsing RSC packet header
  idpf: disable PTM on probe failure and on remove
  idpf: disable DIM work before freeing q_vectors
====================

Link: https://patch.msgid.link/20260908214502.528440-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-10 08:55:12 -07:00
commit fc266a5dd9
6 changed files with 86 additions and 32 deletions

View File

@ -1051,14 +1051,13 @@ int ice_init_hw(struct ice_hw *hw)
hw->evb_veb = true;
/* init xarray for identifying scheduling nodes uniquely */
xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
xa_init_flags(&hw->sched_node_ids, XA_FLAGS_ALLOC);
/* Query the allocated resources for Tx scheduler */
status = ice_sched_query_res_alloc(hw);
if (status) {
ice_debug(hw, ICE_DBG_SCHED, "Failed to get scheduler allocated resources\n");
goto err_unroll_alloc;
goto err_unroll_xarray;
}
ice_sched_get_psm_clk_freq(hw);
@ -1146,6 +1145,8 @@ int ice_init_hw(struct ice_hw *hw)
ice_cleanup_fltr_mgmt_struct(hw);
err_unroll_sched:
ice_sched_cleanup_all(hw);
err_unroll_xarray:
xa_destroy(&hw->sched_node_ids);
err_unroll_alloc:
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
err_unroll_cqinit:
@ -1186,6 +1187,8 @@ void ice_deinit_hw(struct ice_hw *hw)
/* Clear VSI contexts if not already cleared */
ice_clear_all_vsi_ctx(hw);
xa_destroy(&hw->sched_node_ids);
}
/**

View File

@ -371,7 +371,7 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
devm_kfree(ice_hw_to_dev(hw), node->children);
kfree(node->name);
xa_erase(&pi->sched_node_ids, node->id);
xa_erase(&hw->sched_node_ids, node->id);
devm_kfree(ice_hw_to_dev(hw), node);
}
@ -977,7 +977,7 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
if (!new_node->name)
return -ENOMEM;
status = xa_alloc(&pi->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
status = xa_alloc(&hw->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
GFP_KERNEL);
if (status) {
ice_debug(hw, ICE_DBG_SCHED, "xa_alloc failed for sched node status =%d\n",

View File

@ -63,23 +63,33 @@
DECLARE_EVENT_CLASS(ice_rx_dim_template,
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
TP_ARGS(q_vector, dim),
TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
__field(struct dim *, dim)
TP_STRUCT__entry(__field(u16, q_index)
__field(u8, state)
__field(u8, profile_ix)
__field(u8, tune_state)
__field(u8, steps_right)
__field(u8, steps_left)
__field(u8, tired)
__string(devname, q_vector->rx.rx_ring->netdev->name)),
TP_fast_assign(__entry->q_vector = q_vector;
__entry->dim = dim;
TP_fast_assign(__entry->q_index = q_vector->rx.rx_ring->q_index;
__entry->state = dim->state;
__entry->profile_ix = dim->profile_ix;
__entry->tune_state = dim->tune_state;
__entry->steps_right = dim->steps_right;
__entry->steps_left = dim->steps_left;
__entry->tired = dim->tired;
__assign_str(devname);),
TP_printk("netdev: %s Rx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
__get_str(devname),
__entry->q_vector->rx.rx_ring->q_index,
__entry->dim->state,
__entry->dim->profile_ix,
__entry->dim->tune_state,
__entry->dim->steps_right,
__entry->dim->steps_left,
__entry->dim->tired)
__entry->q_index,
__entry->state,
__entry->profile_ix,
__entry->tune_state,
__entry->steps_right,
__entry->steps_left,
__entry->tired)
);
DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
@ -90,23 +100,33 @@ DEFINE_EVENT(ice_rx_dim_template, ice_rx_dim_work,
DECLARE_EVENT_CLASS(ice_tx_dim_template,
TP_PROTO(struct ice_q_vector *q_vector, struct dim *dim),
TP_ARGS(q_vector, dim),
TP_STRUCT__entry(__field(struct ice_q_vector *, q_vector)
__field(struct dim *, dim)
TP_STRUCT__entry(__field(u16, q_index)
__field(u8, state)
__field(u8, profile_ix)
__field(u8, tune_state)
__field(u8, steps_right)
__field(u8, steps_left)
__field(u8, tired)
__string(devname, q_vector->tx.tx_ring->netdev->name)),
TP_fast_assign(__entry->q_vector = q_vector;
__entry->dim = dim;
TP_fast_assign(__entry->q_index = q_vector->tx.tx_ring->q_index;
__entry->state = dim->state;
__entry->profile_ix = dim->profile_ix;
__entry->tune_state = dim->tune_state;
__entry->steps_right = dim->steps_right;
__entry->steps_left = dim->steps_left;
__entry->tired = dim->tired;
__assign_str(devname);),
TP_printk("netdev: %s Tx-Q: %d dim-state: %d dim-profile: %d dim-tune: %d dim-st-right: %d dim-st-left: %d dim-tired: %d",
__get_str(devname),
__entry->q_vector->tx.tx_ring->q_index,
__entry->dim->state,
__entry->dim->profile_ix,
__entry->dim->tune_state,
__entry->dim->steps_right,
__entry->dim->steps_left,
__entry->dim->tired)
__entry->q_index,
__entry->state,
__entry->profile_ix,
__entry->tune_state,
__entry->steps_right,
__entry->steps_left,
__entry->tired)
);
DEFINE_EVENT(ice_tx_dim_template, ice_tx_dim_work,

View File

@ -765,7 +765,6 @@ struct ice_port_info {
/* List contain profile ID(s) and other params per layer */
struct list_head rl_prof_list[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct ice_qos_cfg qos_cfg;
struct xarray sched_node_ids;
u8 is_vf:1;
u8 is_custom_tx_enabled:1;
};
@ -930,6 +929,7 @@ struct ice_hw {
u8 sw_entry_point_layer;
u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct list_head agg_list; /* lists all aggregator */
struct xarray sched_node_ids;
struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI];
u8 evb_veb; /* true for VEB, false for VEPA */

View File

@ -106,6 +106,11 @@ static int idpf_dev_init(struct idpf_adapter *adapter,
*/
static void idpf_decfg_device(struct idpf_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
if (pcie_ptm_enabled(pdev))
pci_disable_ptm(pdev);
libie_pci_unmap_all_mmio_regions(&adapter->ctlq_ctx.mmio_info);
}

View File

@ -3299,6 +3299,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct libeth_rx_pt decoded)
{
u16 rsc_segments, rsc_seg_len;
u16 l3_start = 0;
bool ipv4, ipv6;
int len;
@ -3321,7 +3322,10 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
NAPI_GRO_CB(skb)->count = rsc_segments;
skb_shinfo(skb)->gso_size = rsc_seg_len;
skb_reset_network_header(skb);
if (unlikely(eth_type_vlan(skb->protocol)))
l3_start = VLAN_HLEN;
skb_set_network_header(skb, l3_start);
if (ipv4) {
struct iphdr *ipv4h = ip_hdr(skb);
@ -3329,7 +3333,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
/* Reset and set transport header offset in skb */
skb_set_transport_header(skb, sizeof(struct iphdr));
skb_set_transport_header(skb, l3_start + sizeof(struct iphdr));
len = skb->len - skb_transport_offset(skb);
/* Compute the TCP pseudo header checksum*/
@ -3339,7 +3343,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
skb_set_transport_header(skb, l3_start + sizeof(struct ipv6hdr));
len = skb->len - skb_transport_offset(skb);
tcp_hdr(skb)->check =
~tcp_v6_check(len, &ipv6h->saddr, &ipv6h->daddr, 0);
@ -4145,6 +4149,26 @@ static void idpf_vport_intr_ena_irq_all(struct idpf_vport *vport,
writel(rsrc->noirq_dyn_ctl_ena, rsrc->noirq_dyn_ctl);
}
/**
* idpf_vport_intr_dis_dim_all - Disable DIM work for all q_vectors
* @rsrc: pointer to queue and vector resources
*
* The DIM works are embedded in the q_vector array that
* idpf_vport_intr_rel() frees, and the poll arms them after
* napi_complete_done() has already cleared NAPI_STATE_SCHED. Disable
* rather than just cancel, so that a poll tail still running past
* napi_disable() cannot queue them again behind the drain.
*/
static void idpf_vport_intr_dis_dim_all(struct idpf_q_vec_rsrc *rsrc)
{
for (u16 v_idx = 0; v_idx < rsrc->num_q_vectors; v_idx++) {
struct idpf_q_vector *q_vector = &rsrc->q_vectors[v_idx];
disable_work_sync(&q_vector->tx_dim.work);
disable_work_sync(&q_vector->rx_dim.work);
}
}
/**
* idpf_vport_intr_deinit - Release all vector associations for the vport
* @vport: main vport structure
@ -4155,6 +4179,7 @@ void idpf_vport_intr_deinit(struct idpf_vport *vport,
{
idpf_vport_intr_dis_irq_all(rsrc);
idpf_vport_intr_napi_dis_all(rsrc);
idpf_vport_intr_dis_dim_all(rsrc);
idpf_vport_intr_napi_del_all(rsrc);
idpf_vport_intr_rel_irq(vport, rsrc);
}
@ -4235,7 +4260,6 @@ static void idpf_vport_intr_napi_ena_all(struct idpf_q_vec_rsrc *rsrc)
for (u16 q_idx = 0; q_idx < rsrc->num_q_vectors; q_idx++) {
struct idpf_q_vector *q_vector = &rsrc->q_vectors[q_idx];
idpf_init_dim(q_vector);
napi_enable(&q_vector->napi);
}
}
@ -4578,6 +4602,8 @@ int idpf_vport_intr_alloc(struct idpf_vport *vport,
q_coal = &user_config->q_coalesce[v_idx];
q_vector->vport = vport;
idpf_init_dim(q_vector);
q_vector->tx_itr_value = q_coal->tx_coalesce_usecs;
q_vector->tx_intr_mode = q_coal->tx_intr_mode;
q_vector->tx_itr_idx = VIRTCHNL2_ITR_IDX_1;