Skip to content

Commit

Permalink
net: dsa: refine netdev event notifier
Browse files Browse the repository at this point in the history
Rework the netdev event handler, similar to what the Mellanox Spectrum
driver does, to easily welcome more events later (for example
NETDEV_PRECHANGEUPPER) and use netdev helpers (such as
netif_is_bridge_master).

Signed-off-by: Vivien Didelot <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Acked-by: Ido Schimmel <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
vivien authored and davem330 committed Mar 14, 2016
1 parent 16bfa70 commit 6debb68
Showing 1 changed file with 30 additions and 24 deletions.
54 changes: 30 additions & 24 deletions net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ static int dsa_slave_bridge_port_join(struct net_device *dev,
if (ds->drv->port_bridge_join)
ret = ds->drv->port_bridge_join(ds, p->port, br);

return ret;
return ret == -EOPNOTSUPP ? 0 : ret;
}

static void dsa_slave_bridge_port_leave(struct net_device *dev)
Expand Down Expand Up @@ -1143,40 +1143,46 @@ static bool dsa_slave_dev_check(struct net_device *dev)
return dev->netdev_ops == &dsa_slave_netdev_ops;
}

static int dsa_slave_master_changed(struct net_device *dev)
static int dsa_slave_port_upper_event(struct net_device *dev,
unsigned long event, void *ptr)
{
struct net_device *master = netdev_master_upper_dev_get(dev);
struct dsa_slave_priv *p = netdev_priv(dev);
struct netdev_notifier_changeupper_info *info = ptr;
struct net_device *upper = info->upper_dev;
int err = 0;

if (master && master->rtnl_link_ops &&
!strcmp(master->rtnl_link_ops->kind, "bridge"))
err = dsa_slave_bridge_port_join(dev, master);
else if (dsa_port_is_bridged(p))
dsa_slave_bridge_port_leave(dev);
switch (event) {
case NETDEV_CHANGEUPPER:
if (netif_is_bridge_master(upper)) {
if (info->linking)
err = dsa_slave_bridge_port_join(dev, upper);
else
dsa_slave_bridge_port_leave(dev);
}

return err;
break;
}

return notifier_from_errno(err);
}

int dsa_slave_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
static int dsa_slave_port_event(struct net_device *dev, unsigned long event,
void *ptr)
{
struct net_device *dev;
int err = 0;

switch (event) {
case NETDEV_CHANGEUPPER:
dev = netdev_notifier_info_to_dev(ptr);
if (!dsa_slave_dev_check(dev))
goto out;
return dsa_slave_port_upper_event(dev, event, ptr);
}

err = dsa_slave_master_changed(dev);
if (err && err != -EOPNOTSUPP)
netdev_warn(dev, "failed to reflect master change\n");
return NOTIFY_DONE;
}

break;
}
int dsa_slave_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);

if (dsa_slave_dev_check(dev))
return dsa_slave_port_event(dev, event, ptr);

out:
return NOTIFY_DONE;
}

0 comments on commit 6debb68

Please sign in to comment.