Skip to content
/ linux Public

Commit ea52e95

Browse files
Cosmin Ratiugregkh
authored andcommitted
net/mlx5: qos: Restrict RTNL area to avoid a lock cycle
[ Upstream commit b7e3a5d ] A lock dependency cycle exists where: 1. mlx5_ib_roce_init -> mlx5_core_uplink_netdev_event_replay -> mlx5_blocking_notifier_call_chain (takes notifier_rwsem) -> mlx5e_mdev_notifier_event -> mlx5_netdev_notifier_register -> register_netdevice_notifier_dev_net (takes rtnl) => notifier_rwsem -> rtnl 2. mlx5e_probe -> _mlx5e_probe -> mlx5_core_uplink_netdev_set (takes uplink_netdev_lock) -> mlx5_blocking_notifier_call_chain (takes notifier_rwsem) => uplink_netdev_lock -> notifier_rwsem 3: devlink_nl_rate_set_doit -> devlink_nl_rate_set -> mlx5_esw_devlink_rate_leaf_tx_max_set -> esw_qos_devlink_rate_to_mbps -> mlx5_esw_qos_max_link_speed_get (takes rtnl) -> mlx5_esw_qos_lag_link_speed_get_locked -> mlx5_uplink_netdev_get (takes uplink_netdev_lock) => rtnl -> uplink_netdev_lock => BOOM! (lock cycle) Fix that by restricting the rtnl-protected section to just the necessary part, the call to netdev_master_upper_dev_get and speed querying, so that the last lock dependency is avoided and the cycle doesn't close. This is safe because mlx5_uplink_netdev_get uses netdev_hold to keep the uplink netdev alive while its master device is queried. Use this opportunity to rename the ambiguously-named "hold_rtnl_lock" argument to "take_rtnl" and remove the "_locked" suffix from mlx5_esw_qos_lag_link_speed_get_locked. Fixes: 6b4be64 ("net/mlx5e: Harden uplink netdev access against device unbind") Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Link: https://patch.msgid.link/20260316094603.6999-2-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent c852ebf commit ea52e95

File tree

1 file changed

+9
-14
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/esw

1 file changed

+9
-14
lines changed

drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,45 +1497,40 @@ static int esw_qos_node_enable_tc_arbitration(struct mlx5_esw_sched_node *node,
14971497
return err;
14981498
}
14991499

1500-
static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev)
1500+
static u32 mlx5_esw_qos_lag_link_speed_get(struct mlx5_core_dev *mdev,
1501+
bool take_rtnl)
15011502
{
15021503
struct ethtool_link_ksettings lksettings;
15031504
struct net_device *slave, *master;
15041505
u32 speed = SPEED_UNKNOWN;
15051506

1506-
/* Lock ensures a stable reference to master and slave netdevice
1507-
* while port speed of master is queried.
1508-
*/
1509-
ASSERT_RTNL();
1510-
15111507
slave = mlx5_uplink_netdev_get(mdev);
15121508
if (!slave)
15131509
goto out;
15141510

1511+
if (take_rtnl)
1512+
rtnl_lock();
15151513
master = netdev_master_upper_dev_get(slave);
15161514
if (master && !__ethtool_get_link_ksettings(master, &lksettings))
15171515
speed = lksettings.base.speed;
1516+
if (take_rtnl)
1517+
rtnl_unlock();
15181518

15191519
out:
15201520
mlx5_uplink_netdev_put(mdev, slave);
15211521
return speed;
15221522
}
15231523

15241524
static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max,
1525-
bool hold_rtnl_lock, struct netlink_ext_ack *extack)
1525+
bool take_rtnl,
1526+
struct netlink_ext_ack *extack)
15261527
{
15271528
int err;
15281529

15291530
if (!mlx5_lag_is_active(mdev))
15301531
goto skip_lag;
15311532

1532-
if (hold_rtnl_lock)
1533-
rtnl_lock();
1534-
1535-
*link_speed_max = mlx5_esw_qos_lag_link_speed_get_locked(mdev);
1536-
1537-
if (hold_rtnl_lock)
1538-
rtnl_unlock();
1533+
*link_speed_max = mlx5_esw_qos_lag_link_speed_get(mdev, take_rtnl);
15391534

15401535
if (*link_speed_max != (u32)SPEED_UNKNOWN)
15411536
return 0;

0 commit comments

Comments
 (0)