diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 62f383c84a664ff8478d1cabf3e4457c497907fb..34ac41ac9e610b63e5bf3db276f64b215cce733c 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -5326,46 +5326,61 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port, return err; } -static int rocker_port_master_changed(struct net_device *dev) +static int rocker_port_master_linked(struct rocker_port *rocker_port, + struct net_device *master) +{ + int err = 0; + + if (netif_is_bridge_master(master)) + err = rocker_port_bridge_join(rocker_port, master); + else if (netif_is_ovs_master(master)) + err = rocker_port_ovs_changed(rocker_port, master); + return err; +} + +static int rocker_port_master_unlinked(struct rocker_port *rocker_port) { - struct rocker_port *rocker_port = netdev_priv(dev); - struct net_device *master = netdev_master_upper_dev_get(dev); int err = 0; - /* N.B: Do nothing if the type of master is not supported */ - if (master) { - if (netif_is_bridge_master(master)) - err = rocker_port_bridge_join(rocker_port, master); - else if (netif_is_ovs_master(master)) - err = rocker_port_ovs_changed(rocker_port, master); - } else if (rocker_port_is_bridged(rocker_port)) { + if (rocker_port_is_bridged(rocker_port)) err = rocker_port_bridge_leave(rocker_port); - } else if (rocker_port_is_ovsed(rocker_port)) { + else if (rocker_port_is_ovsed(rocker_port)) err = rocker_port_ovs_changed(rocker_port, NULL); - } - return err; } static int rocker_netdevice_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info; + struct rocker_port *rocker_port; int err; + if (!rocker_port_dev_check(dev)) + return NOTIFY_DONE; + switch (event) { case NETDEV_CHANGEUPPER: - dev = netdev_notifier_info_to_dev(ptr); - if (!rocker_port_dev_check(dev)) - return NOTIFY_DONE; - err = rocker_port_master_changed(dev); - if (err) - netdev_warn(dev, - "failed to reflect master change (err %d)\n", - err); + info = ptr; + if (!info->master) + goto out; + rocker_port = netdev_priv(dev); + if (info->linking) { + err = rocker_port_master_linked(rocker_port, + info->upper_dev); + if (err) + netdev_warn(dev, "failed to reflect master linked (err %d)\n", + err); + } else { + err = rocker_port_master_unlinked(rocker_port); + if (err) + netdev_warn(dev, "failed to reflect master unlinked (err %d)\n", + err); + } break; } - +out: return NOTIFY_DONE; }