Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16cf72bb authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

team: call netdev_change_features out of team lock



Commit f6988cb6 ("team: don't call netdev_change_features under
team->lock") fixed the issue calling netdev_change_features under
team->lock for team_compute_features.

But there are still two places where it calls netdev_change_features
under team->lock, team_port_add and team_port_del. It may cause a
dead lock when the slave port with LRO enabled is added.

This patch is to fix this dead lock by moving netdev_change_features
out of team_port_add and team_port_del, and call it after unlocking
the team lock.

Reported-by: default avatarPatrick Talbert <ptalbert@redhat.com>
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 34b2789f
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
#define TEAM_ENC_FEATURES	(NETIF_F_HW_CSUM | NETIF_F_SG | \
				 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)

static void ___team_compute_features(struct team *team)
static void __team_compute_features(struct team *team)
{
	struct team_port *port;
	u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
@@ -1023,16 +1023,10 @@ static void ___team_compute_features(struct team *team)
		team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
}

static void __team_compute_features(struct team *team)
{
	___team_compute_features(team);
	netdev_change_features(team->dev);
}

static void team_compute_features(struct team *team)
{
	mutex_lock(&team->lock);
	___team_compute_features(team);
	__team_compute_features(team);
	mutex_unlock(&team->lock);
	netdev_change_features(team->dev);
}
@@ -1641,6 +1635,7 @@ static void team_uninit(struct net_device *dev)
	team_notify_peers_fini(team);
	team_queue_override_fini(team);
	mutex_unlock(&team->lock);
	netdev_change_features(dev);
}

static void team_destructor(struct net_device *dev)
@@ -1928,6 +1923,10 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
	mutex_lock(&team->lock);
	err = team_port_add(team, port_dev);
	mutex_unlock(&team->lock);

	if (!err)
		netdev_change_features(dev);

	return err;
}

@@ -1939,6 +1938,10 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
	mutex_lock(&team->lock);
	err = team_port_del(team, port_dev);
	mutex_unlock(&team->lock);

	if (!err)
		netdev_change_features(dev);

	return err;
}