]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: ethtool: keep rtnl_lock for ops using ethtool_op_get_link()
authorJakub Kicinski <kuba@kernel.org>
Wed, 24 Jun 2026 19:04:39 +0000 (12:04 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 25 Jun 2026 17:18:34 +0000 (10:18 -0700)
Breno reports following splats on mlx5:

  RTNL: assertion failed at net/core/dev.c (2241)
  WARNING: net/core/dev.c:2241 at netif_state_change+0xed/0x130, CPU#5: ethtool/1335
  RIP: 0010:netif_state_change+0xf9/0x130
  Call Trace:
    <TASK>
     __linkwatch_sync_dev+0xea/0x120
     ethtool_op_get_link+0xe/0x20
     __ethtool_get_link+0x26/0x40
     linkstate_prepare_data+0x51/0x200
     ethnl_default_doit+0x213/0x470
     genl_family_rcv_msg_doit+0xdd/0x110

Looks like I missed ethtool_op_get_link() trying to sync linkwatch,
which needs rtnl_lock. Not all drivers do this - bnxt doesn't,
it just returns the link state, so add an opt-in bit.

Reported-by: Breno Leitao <leitao@debian.org>
Fixes: 45079e00133e ("net: ethtool: optionally skip rtnl_lock on Netlink path for GET ops")
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: Breno Leitao <leitao@debian.org>
Acked-by: Harshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20260624190439.2521219-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
drivers/net/ethernet/microsoft/mana/mana_ethtool.c
include/linux/ethtool.h
net/ethtool/common.h

index 7cc22916852fb6ce5df6338d504c4747fe678350..8199738ba979ee4c0afd86b690aa81d663ee118b 100644 (file)
@@ -984,7 +984,8 @@ const struct ethtool_ops gve_ethtool_ops = {
        .supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT |
                                 ETHTOOL_RING_USE_RX_BUF_LEN,
        .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
-                        ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
+                        ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+                        ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo = gve_get_drvinfo,
        .get_strings = gve_get_strings,
        .get_sset_count = gve_get_sset_count,
index a615d599b88ee47135db864e0cbfc5fc4d217dff..e7cf12eaa26890b081a134441b408872a168a1d6 100644 (file)
@@ -1855,6 +1855,7 @@ static const struct ethtool_ops iavf_ethtool_ops = {
        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
                                     ETHTOOL_COALESCE_USE_ADAPTIVE,
        .supported_input_xfrm   = RXH_XFRM_SYM_XOR,
+       .op_needs_rtnl          = ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo            = iavf_get_drvinfo,
        .get_link               = ethtool_op_get_link,
        .get_ringparam          = iavf_get_ringparam,
index 2f5b626ba33fe525e22923a58589c26418ecc2fd..112926d07634d765a100d838bc66f3bb821207f0 100644 (file)
@@ -2721,7 +2721,8 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .rxfh_max_num_contexts  = MLX5E_MAX_NUM_RSS,
        .op_needs_rtnl          = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
                                  ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
-                                 ETHTOOL_OP_NEEDS_RTNL_SPFLAGS,
+                                 ETHTOOL_OP_NEEDS_RTNL_SPFLAGS |
+                                 ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
                                     ETHTOOL_COALESCE_MAX_FRAMES |
                                     ETHTOOL_COALESCE_USE_ADAPTIVE |
index 1a8a19f980d33588d66e0f2932044b024bc66d54..c8b76d301c92cf6183bafa1fdc06df13ac3398bd 100644 (file)
@@ -419,7 +419,8 @@ static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
                                     ETHTOOL_COALESCE_MAX_FRAMES |
                                     ETHTOOL_COALESCE_USE_ADAPTIVE,
        .op_needs_rtnl     = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
-                            ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
+                            ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+                            ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo       = mlx5e_rep_get_drvinfo,
        .get_link          = ethtool_op_get_link,
        .get_strings       = mlx5e_rep_get_strings,
index 9b3b32408c64b73c9290eb5ce81f8eb7d4550fe7..01ddc3def9ac07938cfaec026c8b463e81d8aa87 100644 (file)
@@ -286,7 +286,8 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
                                     ETHTOOL_COALESCE_MAX_FRAMES |
                                     ETHTOOL_COALESCE_USE_ADAPTIVE,
        .op_needs_rtnl      = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
-                             ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
+                             ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+                             ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo        = mlx5i_get_drvinfo,
        .get_strings        = mlx5i_get_strings,
        .get_sset_count     = mlx5i_get_sset_count,
@@ -309,6 +310,7 @@ const struct ethtool_ops mlx5i_ethtool_ops = {
 };
 
 const struct ethtool_ops mlx5i_pkey_ethtool_ops = {
+       .op_needs_rtnl      = ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo        = mlx5i_get_drvinfo,
        .get_link           = ethtool_op_get_link,
        .get_ts_info        = mlx5i_get_ts_info,
index cb34fc166ef9683ff1dd3c9cbb5fc4aeb68e70af..0e47088ec44baf56a4d91d39e1bc3c2c88814e6c 100644 (file)
@@ -2024,7 +2024,8 @@ static const struct ethtool_ops fbnic_ethtool_ops = {
                                          ETHTOOL_OP_NEEDS_RTNL_GPAUSEPARAM |
                                          ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM |
                                          ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
-                                         ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
+                                         ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+                                         ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_drvinfo                    = fbnic_get_drvinfo,
        .get_regs_len                   = fbnic_get_regs_len,
        .get_regs                       = fbnic_get_regs,
index 94e658d07a27e85a947e7eb2705806b0b5b8d9c6..881df597d7f9c77d29d9711542fa2cb8c99c15e2 100644 (file)
@@ -597,7 +597,8 @@ static int mana_get_link_ksettings(struct net_device *ndev,
 const struct ethtool_ops mana_ethtool_ops = {
        .supported_coalesce_params = ETHTOOL_COALESCE_RX_CQE_FRAMES,
        .op_needs_rtnl          = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS |
-                                 ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM,
+                                 ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM |
+                                 ETHTOOL_OP_NEEDS_RTNL_GLINK,
        .get_ethtool_stats      = mana_get_ethtool_stats,
        .get_sset_count         = mana_get_sset_count,
        .get_strings            = mana_get_strings,
index 1b834e2a522ec528a4b4b554daf9711edeb5a52b..5d491a98265ef92fdb588ad19b31ff8106a6dae5 100644 (file)
@@ -942,6 +942,7 @@ struct kernel_ethtool_ts_info {
 #define ETHTOOL_OP_NEEDS_RTNL_GPAUSEPARAM      BIT(5)
 #define ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM      BIT(6)
 #define ETHTOOL_OP_NEEDS_RTNL_RSS              BIT(7)
+#define ETHTOOL_OP_NEEDS_RTNL_GLINK            BIT(8)
 
 /**
  * struct ethtool_ops - optional netdev operations
@@ -978,6 +979,7 @@ struct kernel_ethtool_ts_info {
  *      - phylink helpers (note that phydev is currently unsupported!)
  *      - netdev_update_features()
  *      - netif_set_real_num_tx_queues()
+ *      - ethtool_op_get_link() (syncs link watch under rtnl_lock)
  *
  * @get_drvinfo: Report driver/device information. Modern drivers no
  *     longer have to implement this callback. Most fields are
index 2b3847f0080183c887542fb212f9f9e3452f7d00..4e5356e26f400aa0a303e54c072bc0119f11513b 100644 (file)
@@ -113,6 +113,8 @@ ethtool_nl_msg_needs_rtnl(const struct net_device *dev, u8 cmd)
                return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_SPAUSEPARAM;
        case ETHTOOL_MSG_RSS_SET:
                return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_RSS;
+       case ETHTOOL_MSG_LINKSTATE_GET:
+               return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_GLINK;
        case ETHTOOL_MSG_TSCONFIG_GET:
        case ETHTOOL_MSG_TSCONFIG_SET:
                /* tsconfig calls ndos (ndo_hwtstamp_set/get), not ethtool ops.
@@ -159,6 +161,8 @@ ethtool_ioctl_needs_rtnl(const struct net_device *dev, u32 ethcmd)
        case ETHTOOL_SRXFH:
        case ETHTOOL_SRXFHINDIR:
                return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_RSS;
+       case ETHTOOL_GLINK:
+               return ops->op_needs_rtnl & ETHTOOL_OP_NEEDS_RTNL_GLINK;
        }
        return false;
 }