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

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
...@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team, ...@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
#define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ #define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_RXCSUM | NETIF_F_ALL_TSO) 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; struct team_port *port;
u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
...@@ -1023,16 +1023,10 @@ static void ___team_compute_features(struct team *team) ...@@ -1023,16 +1023,10 @@ static void ___team_compute_features(struct team *team)
team->dev->priv_flags |= IFF_XMIT_DST_RELEASE; 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) static void team_compute_features(struct team *team)
{ {
mutex_lock(&team->lock); mutex_lock(&team->lock);
___team_compute_features(team); __team_compute_features(team);
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
netdev_change_features(team->dev); netdev_change_features(team->dev);
} }
...@@ -1641,6 +1635,7 @@ static void team_uninit(struct net_device *dev) ...@@ -1641,6 +1635,7 @@ static void team_uninit(struct net_device *dev)
team_notify_peers_fini(team); team_notify_peers_fini(team);
team_queue_override_fini(team); team_queue_override_fini(team);
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
netdev_change_features(dev);
} }
static void team_destructor(struct net_device *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) ...@@ -1928,6 +1923,10 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
mutex_lock(&team->lock); mutex_lock(&team->lock);
err = team_port_add(team, port_dev); err = team_port_add(team, port_dev);
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
if (!err)
netdev_change_features(dev);
return err; return err;
} }
...@@ -1939,6 +1938,10 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev) ...@@ -1939,6 +1938,10 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
mutex_lock(&team->lock); mutex_lock(&team->lock);
err = team_port_del(team, port_dev); err = team_port_del(team, port_dev);
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
if (!err)
netdev_change_features(dev);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment