Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3699826imu; Mon, 28 Jan 2019 09:15:16 -0800 (PST) X-Google-Smtp-Source: ALg8bN7/Ims2+GW4wXXEUWxp34wqnXMwkem7vCZIsk4j6r87F8thlWoieyet8UHOQb98l0CjUuVI X-Received: by 2002:a63:be4d:: with SMTP id g13mr20701078pgo.378.1548695716273; Mon, 28 Jan 2019 09:15:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548695716; cv=none; d=google.com; s=arc-20160816; b=W8a0skH541vDXjPHRrTG4Tr4tka6DyOzsnJ/9TUo/qDB/HeCRNacmNF5QUifQLV20/ niRNB80/vMZT8ZGpJinI5et2U/dz3UeaTbLx1Jc/EEExjJL2YhcNss/a4zc5plr8jjIE L/3NwDQNg3qqqpgZwxng5GxNpTc08UmxgrHV9R/Frg7IDy11UvrvMcdIcvmpCxC8omP8 S8QCBJNDCcOyZenouhm6dmMeKHyPiakEE8D3lCdw0vxPOZ/bGYccNFnAS6HhdrnzpxZS a7uhTGqwIqvGvv5V5ddjEOYbIGjUgF96lCLqvJSOXml2ogOSj7fqAMj/eiYar8C8Fs0e qZUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=vl3gobP3nuNNu1U0cWok8b5sJjAVRZiNCi41uDM/Xdg=; b=yyIfWxaNftAdxC5ZKwV7ih7At6rNfoxng+7xcl4uxhH+i8TWlDxbgH+HtPZBMjtMc4 TPWdp4+ykoTtjv8qdLFav0pdQwoLd/m16zv5+uC0xtYLhwZIVfQgxt5qN1wLZhm3hyWd Sl/996Rt8YztRddi/DXwaIUiabn2qQgYDEOaoE4fgxA4CHL9F23gSbZjCKijJqj62tSP cVua8QgzlDaRJQ9//M8WZtJI4sAvnbRkhKFlCxHzKiTesKHtovmmiUnNeV53BvPuc9Dw iOW230pgC4Cy1yxhm8SM9WWMsIrfymkLIi7AsTHFVx0gtdvSOOYP82jCPuPb1XChZk4q kLOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="2r/4hTd0"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m4si22188925pgk.399.2019.01.28.09.14.57; Mon, 28 Jan 2019 09:15:16 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="2r/4hTd0"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732410AbfA1RNk (ORCPT + 99 others); Mon, 28 Jan 2019 12:13:40 -0500 Received: from mail.kernel.org ([198.145.29.99]:60016 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732372AbfA1QIU (ORCPT ); Mon, 28 Jan 2019 11:08:20 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3F3D621738; Mon, 28 Jan 2019 16:08:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1548691699; bh=+Bbr9dE8vhv6Yz/kM/KgY8bsmY8DWJN9zSexGBQ19tY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2r/4hTd07uDSZifiNBCnNceQjAJ7S56wd0vU3PjfXeF72ziOveTG2jv1sLbp6JosH fus8YSHgGkrqMS6mVW4fkWCXef2WC5Dlutylq2GTaBxTwKt5D5IyP6kSdsXTOrnTp2 edhRsVnKox6HPnisphb6hzJi3ZzNcloranVjfRHg= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Ido Schimmel , "David S . Miller" , Sasha Levin , netdev@vger.kernel.org Subject: [PATCH AUTOSEL 4.19 189/258] mlxsw: spectrum: Properly cleanup LAG uppers when removing port from LAG Date: Mon, 28 Jan 2019 10:58:15 -0500 Message-Id: <20190128155924.51521-189-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190128155924.51521-1-sashal@kernel.org> References: <20190128155924.51521-1-sashal@kernel.org> MIME-Version: 1.0 X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ido Schimmel [ Upstream commit be2d6f421f680e01d58f7cd452646e0d8586d49b ] When a LAG device or a VLAN device on top of it is enslaved to a bridge, the driver propagates the CHANGEUPPER event to the LAG's slaves. This causes each physical port to increase the reference count of the internal representation of the bridge port by calling mlxsw_sp_port_bridge_join(). However, when a port is removed from a LAG, the corresponding leave() function is not called and the reference count is not decremented. This leads to ugly hacks such as mlxsw_sp_bridge_port_should_destroy() that try to understand if the bridge port should be destroyed even when its reference count is not 0. Instead, make sure that when a port is unlinked from a LAG it would see the same events as if the LAG (or its uppers) were unlinked from a bridge. The above is achieved by walking the LAG's uppers when a port is unlinked and calling mlxsw_sp_port_bridge_leave() for each upper that is enslaved to a bridge. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- .../net/ethernet/mellanox/mlxsw/spectrum.c | 23 ++++++++++++++++ .../mellanox/mlxsw/spectrum_switchdev.c | 27 +------------------ 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index de821a9fdfaf..d64cd8d44d83 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4235,6 +4235,25 @@ void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port) dev_put(mlxsw_sp_port->dev); } +static void +mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port, + struct net_device *lag_dev) +{ + struct net_device *br_dev = netdev_master_upper_dev_get(lag_dev); + struct net_device *upper_dev; + struct list_head *iter; + + if (netif_is_bridge_port(lag_dev)) + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, br_dev); + + netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) { + if (!netif_is_bridge_port(upper_dev)) + continue; + br_dev = netdev_master_upper_dev_get(upper_dev); + mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, br_dev); + } +} + static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id) { char sldr_pl[MLXSW_REG_SLDR_LEN]; @@ -4427,6 +4446,10 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, /* Any VLANs configured on the port are no longer valid */ mlxsw_sp_port_vlan_flush(mlxsw_sp_port); + /* Make the LAG and its directly linked uppers leave bridges they + * are memeber in + */ + mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev); if (lag->ref_count == 1) mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0d9ea37c5d21..cdec48bcc6ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -282,30 +282,6 @@ mlxsw_sp_bridge_port_destroy(struct mlxsw_sp_bridge_port *bridge_port) kfree(bridge_port); } -static bool -mlxsw_sp_bridge_port_should_destroy(const struct mlxsw_sp_bridge_port * - bridge_port) -{ - struct net_device *dev = bridge_port->dev; - struct mlxsw_sp *mlxsw_sp; - - if (is_vlan_dev(dev)) - mlxsw_sp = mlxsw_sp_lower_get(vlan_dev_real_dev(dev)); - else - mlxsw_sp = mlxsw_sp_lower_get(dev); - - /* In case ports were pulled from out of a bridged LAG, then - * it's possible the reference count isn't zero, yet the bridge - * port should be destroyed, as it's no longer an upper of ours. - */ - if (!mlxsw_sp && list_empty(&bridge_port->vlans_list)) - return true; - else if (bridge_port->ref_count == 0) - return true; - else - return false; -} - static struct mlxsw_sp_bridge_port * mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge, struct net_device *brport_dev) @@ -343,8 +319,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge, { struct mlxsw_sp_bridge_device *bridge_device; - bridge_port->ref_count--; - if (!mlxsw_sp_bridge_port_should_destroy(bridge_port)) + if (--bridge_port->ref_count != 0) return; bridge_device = bridge_port->bridge_device; mlxsw_sp_bridge_port_destroy(bridge_port); -- 2.19.1