From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A0DE276041 for ; Thu, 23 Jul 2026 02:28:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784773740; cv=none; b=NpKmtrktpDYcsGFtAYKyUPjQegJLafzUQ1vSjb4KhPeVsmSZu613HP4X1ltl2+8VWmF/egZUPGvFE3j7TZec1zdlYRISr13WikzzRBofr2b5e7i3jA8HhHtGZRPkbe4C9811SV5tW//v1R5Kl/INweGarDn5DQu8vvX+WPztdt8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784773740; c=relaxed/simple; bh=rSTOYgP5C4V77SuZFDQkiN+H0p7vbVFqiDEaObp9C+c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hkjKaqvZ9uoMPnUMdnplpw6qVJDtK+8CYBDnnCEEAvRRIvNDOQt4JEhc4mGJm9kb16lyev2VgN9rxODci2/5+V3GLoA5bnmw37TW5udlypJrZFEPCBu3eCSGQSq/DHozQGG5c7AnN7eCNbQr7thH8fvTXb9iWYgYYpxQDEerVQE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NANGZTEV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NANGZTEV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C87B1F000E9; Thu, 23 Jul 2026 02:28:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784773738; bh=ObNMxTJUgW4Ui9UT0J2cvOKOZHXyuGmNZd035S8TzfI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NANGZTEVJokILodsFcSi53Q045EUl19gm/ApQ5Fh4YXa7OB89lqndsfkuC/m6x2tN Ff9RuaxJr5jSpFDj7/+ay6SQbnzlE35zkW7Il0IIM4fKMm5UIMuoXQP5smAcQcYsj+ XsNfJhplgHRnqYzvSTWpKQamPmcdPI++k7ckUy82vUud7evl0j3s1T6UbQNPp63awV qF5aIAb/jgLa56q5lBQ0W1uOrQX6E5ed6BiRnSPgL+fa8b1W1lI8eUtmxDZKNDdnCZ JmjNK5a+d4HbBuNFhwAsSOdEuSKw42hFcJmjVFzzqWBVNnNT8q5QJ7h4ci2WNJv1gs IgSNZpepQzCnA== From: Sasha Levin To: stable@vger.kernel.org Cc: Petr Machata , Danielle Ratson , "David S. Miller" , Sasha Levin Subject: [PATCH 5.10.y 2/3] mlxsw: spectrum: On port enslavement to a LAG, join upper's bridges Date: Wed, 22 Jul 2026 22:28:55 -0400 Message-ID: <20260723022856.2844792-2-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260723022856.2844792-1-sashal@kernel.org> References: <2026072025-thirsting-chance-450b@gregkh> <20260723022856.2844792-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Petr Machata [ Upstream commit 987c7782f0627e1c87617458806a7e6c1995678a ] Currently it never happens that a netdevice that is already a bridge slave would suddenly become mlxsw upper. The only case where this might be possible as far as mlxsw is concerned, is with LAG netdevices. But if a LAG already has an upper, enslaving mlxsw port to that LAG is forbidden. Thus the only way to install a LAG between a bridge and a mlxsw port is by first enslaving the port to the LAG, and then enslaving that LAG to a bridge. However in the following patches, the requirement that ports be only enslaved to masters without uppers, is going to be relaxed. It will therefore be necessary to join bridges of LAG uppers. Without this replay, the mlxsw bridge_port objects are not instantiated, which causes issues later, as a lot of code relies on their presence. Therefore in this patch, when the first mlxsw physical netdevice is enslaved to a LAG, consider bridges upper to the LAG (both the direct master, if any, and any bridge masters of VLAN uppers), and have the relevant netdevices join their bridges. Signed-off-by: Petr Machata Reviewed-by: Danielle Ratson Signed-off-by: David S. Miller Stable-dep-of: 41c8c1d65b32 ("mlxsw: fix refcount leak in mlxsw_sp_port_lag_join()") Signed-off-by: Sasha Levin --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index f8d15a76eede69..a7d2c59690ad90 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3549,6 +3549,88 @@ static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp, return -EBUSY; } +static int mlxsw_sp_lag_uppers_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev, + struct netlink_ext_ack *extack) +{ + struct net_device *upper_dev; + struct net_device *master; + struct list_head *iter; + int done = 0; + int err; + + master = netdev_master_upper_dev_get(lag_dev); + if (master && netif_is_bridge_master(master)) { + err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, lag_dev, master, + extack); + if (err) + return err; + } + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (master && netif_is_bridge_master(master)) { + err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, + upper_dev, master, + extack); + if (err) + goto err_port_bridge_join; + } + + ++done; + } + + return 0; + +err_port_bridge_join: + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (!master || !netif_is_bridge_master(master)) + continue; + + if (!done--) + break; + + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master); + } + + master = netdev_master_upper_dev_get(lag_dev); + if (master && netif_is_bridge_master(master)) + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master); + + return err; +} + +static void +mlxsw_sp_lag_uppers_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev) +{ + struct net_device *upper_dev; + struct net_device *master; + struct list_head *iter; + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!is_vlan_dev(upper_dev)) + continue; + + master = netdev_master_upper_dev_get(upper_dev); + if (!master) + continue; + + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master); + } + + master = netdev_master_upper_dev_get(lag_dev); + if (master) + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master); +} + static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *lag_dev, struct netlink_ext_ack *extack) @@ -3573,6 +3655,12 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index); if (err) return err; + + err = mlxsw_sp_lag_uppers_bridge_join(mlxsw_sp_port, lag_dev, + extack); + if (err) + goto err_lag_uppers_bridge_join; + err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index); if (err) goto err_col_port_add; @@ -3602,6 +3690,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_sp_port->local_port); mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id); err_col_port_add: + mlxsw_sp_lag_uppers_bridge_leave(mlxsw_sp_port, lag_dev); +err_lag_uppers_bridge_join: if (!lag->ref_count) mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); return err; -- 2.53.0