diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index b4906a8d24ef..7adad781e9b5 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -177,9 +177,12 @@ static int ipvlan_init(struct net_device *dev) if (!ipvlan->pcpu_stats) return -ENOMEM; + netdev_lock(phy_dev); + if (!netif_is_ipvlan_port(phy_dev)) { err = ipvlan_port_create(phy_dev); if (err < 0) { + netdev_unlock(phy_dev); free_percpu(ipvlan->pcpu_stats); return err; } @@ -190,6 +193,8 @@ static int ipvlan_init(struct net_device *dev) refcount_inc(&port->count); } + netdev_unlock(phy_dev); + ipvlan->port = port; return 0; @@ -198,9 +203,19 @@ static int ipvlan_init(struct net_device *dev) static void ipvlan_uninit(struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); + netdevice_tracker dev_tracker; + struct net_device *phy_dev; free_percpu(ipvlan->pcpu_stats); + + phy_dev = ipvlan->phy_dev; + netdev_hold(phy_dev, &dev_tracker, GFP_KERNEL); + netdev_lock(phy_dev); + ipvlan_port_put(ipvlan->port); + + netdev_unlock(phy_dev); + netdev_put(phy_dev, &dev_tracker); } static int ipvlan_open(struct net_device *dev)