mlx5 misc fixes 2026-01-26
Subsystems (5)
Tariq Toukan
maintainercover mlx5 misc fixes 2026-01-26
Hi,
This patchset provides misc bug fixes from the team to the mlx5 core and Eth drivers.
Thanks,
Tariq.
Gal Pressman (1):
net/mlx5e: Account for netdev stats in ndo_get_stats64
Mark Bloch (1):
net/mlx5e: TC, delete flows only for existing peers
Shay Drory (1):
net/mlx5: Fix Unbinding uplink-netdev in switchdev mode
drivers/net/ethernet/mellanox/mlx5/core/dev.c | 14 ++++++++++ .../net/ethernet/mellanox/mlx5/core/en_main.c | 21 ++++++++------- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 19 +++++++++----- .../net/ethernet/mellanox/mlx5/core/eswitch.h | 4 +++ .../mellanox/mlx5/core/eswitch_offloads.c | 26 +++++++++++++++++++ .../ethernet/mellanox/mlx5/core/mlx5_core.h | 1 + 6 files changed, 70 insertions(+), 15 deletions(-)
base-commit: 709bbb015538dfd5c97308b77c950d41a4d95cd3
Signature · 1 line
2.40.1
Tariq Toukan
maintainerPATCH 1/3 net/mlx5: Fix Unbinding uplink-netdev in switchdev mode
From: Shay Drory <[email protected]>
It is possible to unbind the uplink ETH driver while the E-Switch is in switchdev mode. This leads to netdevice reference counting issues[1], as the driver removal path was not designed to clean up from this state.
During uplink ETH driver removal (_mlx5e_remove), the code now waits for any concurrent E-Switch mode transition to finish. It then removes the REPs auxiliary device, if exists. This ensures a graceful cleanup.
[1]unregister_netdevice: waiting for eth2 to become free. Usage count = 2ref_tracker: netdev@00000000c912e04b has 1/1 users at
ib_device_set_netdev+0x130/0x270 [ib_core]
mlx5_ib_vport_rep_load+0xf4/0x3e0 [mlx5_ib]
mlx5_esw_offloads_rep_load+0xc7/0xe0 [mlx5_core]
esw_offloads_enable+0x583/0x900 [mlx5_core]
mlx5_eswitch_enable_locked+0x1b2/0x290 [mlx5_core]
mlx5_devlink_eswitch_mode_set+0x107/0x3e0 [mlx5_core]
devlink_nl_eswitch_set_doit+0x60/0xd0
genl_family_rcv_msg_doit+0xe0/0x130
genl_rcv_msg+0x183/0x290
netlink_rcv_skb+0x4b/0xf0
genl_rcv+0x24/0x40
netlink_unicast+0x255/0x380
netlink_sendmsg+0x1f3/0x420
__sock_sendmsg+0x38/0x60
__sys_sendto+0x119/0x180
__x64_sys_sendto+0x20/0x30--- drivers/net/ethernet/mellanox/mlx5/core/dev.c | 14 ++++++++++ .../net/ethernet/mellanox/mlx5/core/en_main.c | 1 + .../net/ethernet/mellanox/mlx5/core/eswitch.h | 4 +++ .../mellanox/mlx5/core/eswitch_offloads.c | 26 +++++++++++++++++++ .../ethernet/mellanox/mlx5/core/mlx5_core.h | 1 + 5 files changed, 46 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/dev.c +14 -0
@@ -575,3 +575,17 @@ bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_devreturn plen && flen && flen == plen && !memcmp (fsystem_guid, psystem_guid, flen); } + +void mlx5_core_reps_aux_devs_remove (struct mlx5_core_dev *dev) +{ +struct mlx5_priv *priv = &dev->priv; + +if (priv->adev[MLX5_INTERFACE_PROTOCOL_ETH ]) +device_lock_assert (&priv->adev[MLX5_INTERFACE_PROTOCOL_ETH ]->adev.dev); +else +mlx5_core_err (dev,"ETH driver already removed\n" ); +if (priv->adev[MLX5_INTERFACE_PROTOCOL_IB_REP ]) +del_adev (&priv->adev[MLX5_INTERFACE_PROTOCOL_IB_REP ]->adev); +if (priv->adev[MLX5_INTERFACE_PROTOCOL_ETH_REP ]) +del_adev (&priv->adev[MLX5_INTERFACE_PROTOCOL_ETH_REP ]->adev); +}
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +1 -0
@@ -6842,6 +6842,7 @@ static void _mlx5e_remove(struct auxiliary_device *adev)struct mlx5e_priv *priv =netdev_priv (netdev);struct mlx5_core_dev *mdev = edev->mdev; +mlx5_eswitch_safe_aux_devs_remove (mdev);mlx5_core_uplink_netdev_set (mdev,NULL );if (priv->profile)
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +4 -0
@@ -929,6 +929,7 @@ int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vint mlx5_esw_ipsec_vf_packet_offload_supported (struct mlx5_core_dev *dev,u16 vport_num);bool mlx5_esw_host_functions_enabled (const struct mlx5_core_dev *dev); +void mlx5_eswitch_safe_aux_devs_remove (struct mlx5_core_dev *dev);#else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init (struct mlx5_core_dev *dev) {return 0 ; }
@@ -1012,6 +1013,9 @@ mlx5_esw_vport_vhca_id(struct mlx5_eswitch *esw, u16 vportn, u16 *vhca_id)return false; } +static inline void +mlx5_eswitch_safe_aux_devs_remove (struct mlx5_core_dev *dev) {} +#endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESWITCH_H__ */
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +26 -0
@@ -3981,6 +3981,32 @@ static bool mlx5_devlink_switchdev_active_mode_change(struct mlx5_eswitch *esw,return true; } +#define MLX5_ESW_HOLD_TIMEOUT_MS 7000 +#define MLX5_ESW_HOLD_RETRY_DELAY_MS 500 + +void mlx5_eswitch_safe_aux_devs_remove (struct mlx5_core_dev *dev) +{ +unsigned long timeout; +bool hold_esw = true; + +/* Wait for any concurrent eswitch mode transition to complete. */ +if (!mlx5_esw_hold (dev)) { + timeout = jiffies +msecs_to_jiffies (MLX5_ESW_HOLD_TIMEOUT_MS ); +while (!mlx5_esw_hold (dev)) { +if (!time_before (jiffies, timeout)) { + hold_esw = false; +break ; + } +msleep (MLX5_ESW_HOLD_RETRY_DELAY_MS ); + } + } +if (hold_esw) { +if (mlx5_eswitch_mode (dev) ==MLX5_ESWITCH_OFFLOADS ) +mlx5_core_reps_aux_devs_remove (dev); +mlx5_esw_release (dev); + } +} +int mlx5_devlink_eswitch_mode_set (struct devlink *devlink,u16 mode,struct netlink_ext_ack *extack) {
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +1 -0
@@ -290,6 +290,7 @@ int mlx5_register_device(struct mlx5_core_dev *dev);void mlx5_unregister_device (struct mlx5_core_dev *dev);void mlx5_dev_set_lightweight (struct mlx5_core_dev *dev);bool mlx5_dev_is_lightweight (struct mlx5_core_dev *dev); +void mlx5_core_reps_aux_devs_remove (struct mlx5_core_dev *dev);void mlx5_fw_reporters_create (struct mlx5_core_dev *dev);int mlx5_query_mtpps (struct mlx5_core_dev *dev,u32 *mtpps,u32 mtpps_size);
Signature · 1 line
2.40.1
Tariq Toukan
maintainerPATCH 2/3 net/mlx5e: TC, delete flows only for existing peers
In reply to Tariq ToukanFrom: Mark Bloch <[email protected]>
When deleting TC steering flows, iterate only over actual devcom peers instead of assuming all possible ports exist. This avoids touching non-existent peers and ensures cleanup is limited to devices the driver is currently connected to.
BUG: kernel NULL pointer dereference, address: 0000000000000008 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page PGD 133c8a067 P4D 0 Oops: Oops: 0002 [#1] SMP CPU: 19 UID: 0 PID: 2169 Comm: tc Not tainted 6.18.0+ #156 NONE Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 RIP: 0010:mlx5e_tc_del_fdb_peers_flow+0xbe/0x200 [mlx5_core] Code: 00 00 a8 08 74 a8 49 8b 46 18 f6 c4 02 74 9f 4c 8d bf a0 12 00 00 4c 89 ff e8 0e e7 96 e1 49 8b 44 24 08 49 8b 0c 24 4c 89 ff <48> 89 41 08 48 89 08 49 89 2c 24 49 89 5c 24 08 e8 7d ce 96 e1 49 RSP: 0018:ff11000143867528 EFLAGS: 00010246 RAX: 0000000000000000 RBX: dead000000000122 RCX: 0000000000000000 RDX: ff11000143691580 RSI: ff110001026e5000 RDI: ff11000106f3d2a0 RBP: dead000000000100 R08: 00000000000003fd R09: 0000000000000002 R10: ff11000101c75690 R11: ff1100085faea178 R12: ff11000115f0ae78 R13: 0000000000000000 R14: ff11000115f0a800 R15: ff11000106f3d2a0 FS: 00007f35236bf740(0000) GS:ff110008dc809000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 0000000157a01001 CR4: 0000000000373eb0 Call Trace: <TASK> mlx5e_tc_del_flow+0x46/0x270 [mlx5_core] mlx5e_flow_put+0x25/0x50 [mlx5_core] mlx5e_delete_flower+0x2a6/0x3e0 [mlx5_core] tc_setup_cb_reoffload+0x20/0x80 fl_reoffload+0x26f/0x2f0 [cls_flower] ? mlx5e_tc_reoffload_flows_work+0xc0/0xc0 [mlx5_core] ? mlx5e_tc_reoffload_flows_work+0xc0/0xc0 [mlx5_core] tcf_block_playback_offloads+0x9e/0x1c0 tcf_block_unbind+0x7b/0xd0 tcf_block_setup+0x186/0x1d0 tcf_block_offload_cmd.isra.0+0xef/0x130 tcf_block_offload_unbind+0x43/0x70 __tcf_block_put+0x85/0x160 ingress_destroy+0x32/0x110 [sch_ingress] __qdisc_destroy+0x44/0x100 qdisc_graft+0x22b/0x610 tc_get_qdisc+0x183/0x4d0 rtnetlink_rcv_msg+0x2d7/0x3d0 ? rtnl_calcit.isra.0+0x100/0x100 netlink_rcv_skb+0x53/0x100 netlink_unicast+0x249/0x320 ? __alloc_skb+0x102/0x1f0 netlink_sendmsg+0x1e3/0x420 __sock_sendmsg+0x38/0x60 ____sys_sendmsg+0x1ef/0x230 ? copy_msghdr_from_user+0x6c/0xa0 ___sys_sendmsg+0x7f/0xc0 ? ___sys_recvmsg+0x8a/0xc0 ? __sys_sendto+0x119/0x180 __sys_sendmsg+0x61/0xb0 do_syscall_64+0x55/0x640 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x7f35238bb764 Code: 15 b9 86 0c 00 f7 d8 64 89 02 b8 ff ff ff ff eb bf 0f 1f 44 00 00 f3 0f 1e fa 80 3d e5 08 0d 00 00 74 13 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 4c c3 0f 1f 00 55 48 89 e5 48 83 ec 20 89 55 RSP: 002b:00007ffed4c35638 EFLAGS: 00000202 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 000055a2efcc75e0 RCX: 00007f35238bb764 RDX: 0000000000000000 RSI: 00007ffed4c356a0 RDI: 0000000000000003 RBP: 00007ffed4c35710 R08: 0000000000000010 R09: 00007f3523984b20 R10: 0000000000000004 R11: 0000000000000202 R12: 00007ffed4c35790 R13: 000000006947df8f R14: 000055a2efcc75e0 R15: 00007ffed4c35780
--- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +13 -6
@@ -2147,11 +2147,14 @@ static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow,static void mlx5e_tc_del_fdb_peers_flow (struct mlx5e_tc_flow *flow) { +struct mlx5_devcom_comp_dev *devcom; +struct mlx5_devcom_comp_dev *pos; +struct mlx5_eswitch *peer_esw;int i; -for (i =0 ; i <MLX5_MAX_PORTS ; i++) { -if (i ==mlx5_get_dev_index (flow->priv->mdev)) -continue ; + devcom = flow->priv->mdev->priv.eswitch->devcom; +mlx5_devcom_for_each_peer_entry (devcom, peer_esw, pos) { + i =mlx5_get_dev_index (peer_esw->dev);mlx5e_tc_del_fdb_peer_flow (flow, i); } }
@@ -5513,12 +5516,16 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags)void mlx5e_tc_clean_fdb_peer_flows (struct mlx5_eswitch *esw) { +struct mlx5_devcom_comp_dev *devcom; +struct mlx5_devcom_comp_dev *pos;struct mlx5e_tc_flow *flow, *tmp; +struct mlx5_eswitch *peer_esw;int i; -for (i =0 ; i <MLX5_MAX_PORTS ; i++) { -if (i ==mlx5_get_dev_index (esw->dev)) -continue ; + devcom = esw->devcom; + +mlx5_devcom_for_each_peer_entry (devcom, peer_esw, pos) { + i =mlx5_get_dev_index (peer_esw->dev);list_for_each_entry_safe (flow, tmp, &esw->offloads.peer_flows[i], peer[i])mlx5e_tc_del_fdb_peers_flow (flow); }
Signature · 1 line
2.40.1
Tariq Toukan
maintainerPATCH 3/3 net/mlx5e: Account for netdev stats in ndo_get_stats64
In reply to Tariq ToukanFrom: Gal Pressman <[email protected]>
The driver's ndo_get_stats64 callback is only reporting mlx5 counters, without accounting for the netdev stats, causing errors from the network stack to be invisible in statistics.
Add netdev_stats_to_stats64() call to first populate the counters, then add mlx5 counters on top, ensuring both are accounted for (where appropriate).
--- .../net/ethernet/mellanox/mlx5/core/en_main.c | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +11 -9
@@ -4052,6 +4052,8 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)mlx5e_queue_update_stats (priv); } +netdev_stats_to_stats64 (stats, &dev->stats); +if (mlx5e_is_uplink_rep (priv)) {struct mlx5e_vport_stats *vstats = &priv->stats.vport;
@@ -4068,21 +4070,21 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)mlx5e_fold_sw_stats64 (priv, stats); } - stats->rx_missed_errors = priv->stats.qcnt.rx_out_of_buffer; - stats->rx_dropped =PPORT_2863_GET (pstats, if_in_discards); + stats->rx_missed_errors += priv->stats.qcnt.rx_out_of_buffer; + stats->rx_dropped +=PPORT_2863_GET (pstats, if_in_discards); - stats->rx_length_errors = + stats->rx_length_errors +=PPORT_802_3_GET (pstats, a_in_range_length_errors) +PPORT_802_3_GET (pstats, a_out_of_range_length_field) +PPORT_802_3_GET (pstats, a_frame_too_long_errors) +VNIC_ENV_GET (&priv->stats.vnic, eth_wqe_too_small); - stats->rx_crc_errors = + stats->rx_crc_errors +=PPORT_802_3_GET (pstats, a_frame_check_sequence_errors); - stats->rx_frame_errors =PPORT_802_3_GET (pstats, a_alignment_errors); - stats->tx_aborted_errors =PPORT_2863_GET (pstats, if_out_discards); - stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + - stats->rx_frame_errors; - stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors; + stats->rx_frame_errors +=PPORT_802_3_GET (pstats, a_alignment_errors); + stats->tx_aborted_errors +=PPORT_2863_GET (pstats, if_out_discards); + stats->rx_errors += stats->rx_length_errors + stats->rx_crc_errors + + stats->rx_frame_errors; + stats->tx_errors += stats->tx_aborted_errors + stats->tx_carrier_errors; }static void mlx5e_nic_set_rx_mode (struct mlx5e_priv *priv)
Signature · 1 line
2.40.1
Jakub Kicinski
maintainerRe: [PATCH net 3/3] net/mlx5e: Account for netdev stats in ndo_get_stats64
Quoted 3 lines · On Mon, 26 Jan 2026 09:14:55 +0200 Tariq Toukan wrote:
The driver's
ndo_get_stats64callback is only reporting mlx5 counters, without accounting for the netdev stats, causing errors from the network stack to be invisible in statistics.
I cooked up a patch to fix this generically in the core... but I can't actually find any "errors from the network stack" that are accounted to dev->stats. Could you be more specific about the issues you were seeing?
Re: [PATCH net 3/3] net/mlx5e: Account for netdev stats in ndo_get_stats64
Quoted 9 lines · Jakub Kicinski
Quoted 3 lines · On Mon, 26 Jan 2026 09:14:55 +0200 Tariq Toukan wrote:
The driver's
ndo_get_stats64callback is only reporting mlx5 counters, without accounting for the netdev stats, causing errors from the network stack to be invisible in statistics.I cooked up a patch to fix this generically in the core... but I can't actually find any "errors from the network stack" that are accounted to
dev->stats. Could you be more specific about the issues you were seeing?
My original motivation was identifying packet drops in the GRE stack, specifically in gre_rcv() after an error in gre_parse_header() (in my case, due to a checksum error).
Currently, these packets are silently dropped. I have additional patches that increment the rx_dropped/rx_crc_errors counters in that path, which exposed the issue, but they haven't been submitted yet.
However, you are right that it's hard to find existing dev->stats increments, the use case this currently fixes is an error in __bpf_redirect_neigh_v4()/__bpf_redirect_neigh_v6().
Quoted 9 lines · Tariq Toukan
Hi,
This patchset provides misc bug fixes from the team to the mlx5 core and Eth drivers.
Thanks,
Tariq.
Quoted 8 lines
Gal Pressman (1):
net/mlx5e: Account for netdev stats inndo_get_stats64Mark Bloch (1):
net/mlx5e: TC, delete flows only for existing peersShay Drory (1):
net/mlx5: Fix Unbinding uplink-netdev in switchdev mode
Thanks,
For the series:
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 9 lines · On Mon, 26 Jan 2026 09:14:52 +0200 you wrote:
Hi,
This patchset provides misc bug fixes from the team to the mlx5 core and Eth drivers.
Thanks,
Tariq.[...]
Here is the summary with links:
- [net,1/3] net/mlx5: Fix Unbinding uplink-netdev in switchdev mode
https://git.kernel.org/netdev/net/c/2ae8c7edea87 - [net,2/3] net/mlx5e: TC, delete flows only for existing peers https://git.kernel.org/netdev/net/c/f67666938ae6 - [net,3/3] net/mlx5e: Account for netdev stats in ndo_get_stats64 https://git.kernel.org/netdev/net/c/476681f10cc1
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html