aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/slave.c
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2016-03-13 16:21:34 -0400
committerDavid S. Miller <davem@davemloft.net>2016-03-14 16:05:32 -0400
commit6debb68a2d1acd1f5eca1d9d1c79a54dc998b6d6 (patch)
treed5cd4d18aca824a81c59800c3b29edbca623a488 /net/dsa/slave.c
parent16bfa7024eba5e36aff38ba62086b9027373007d (diff)
net: dsa: refine netdev event notifier
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 <vivien.didelot@savoirfairelinux.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Acked-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/slave.c')
-rw-r--r--net/dsa/slave.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 8e00f1d83eb8..a575f0350d5a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -451,7 +451,7 @@ static int dsa_slave_bridge_port_join(struct net_device *dev,
451 if (ds->drv->port_bridge_join) 451 if (ds->drv->port_bridge_join)
452 ret = ds->drv->port_bridge_join(ds, p->port, br); 452 ret = ds->drv->port_bridge_join(ds, p->port, br);
453 453
454 return ret; 454 return ret == -EOPNOTSUPP ? 0 : ret;
455} 455}
456 456
457static void dsa_slave_bridge_port_leave(struct net_device *dev) 457static void dsa_slave_bridge_port_leave(struct net_device *dev)
@@ -1143,40 +1143,46 @@ static bool dsa_slave_dev_check(struct net_device *dev)
1143 return dev->netdev_ops == &dsa_slave_netdev_ops; 1143 return dev->netdev_ops == &dsa_slave_netdev_ops;
1144} 1144}
1145 1145
1146static int dsa_slave_master_changed(struct net_device *dev) 1146static int dsa_slave_port_upper_event(struct net_device *dev,
1147 unsigned long event, void *ptr)
1147{ 1148{
1148 struct net_device *master = netdev_master_upper_dev_get(dev); 1149 struct netdev_notifier_changeupper_info *info = ptr;
1149 struct dsa_slave_priv *p = netdev_priv(dev); 1150 struct net_device *upper = info->upper_dev;
1150 int err = 0; 1151 int err = 0;
1151 1152
1152 if (master && master->rtnl_link_ops && 1153 switch (event) {
1153 !strcmp(master->rtnl_link_ops->kind, "bridge")) 1154 case NETDEV_CHANGEUPPER:
1154 err = dsa_slave_bridge_port_join(dev, master); 1155 if (netif_is_bridge_master(upper)) {
1155 else if (dsa_port_is_bridged(p)) 1156 if (info->linking)
1156 dsa_slave_bridge_port_leave(dev); 1157 err = dsa_slave_bridge_port_join(dev, upper);
1158 else
1159 dsa_slave_bridge_port_leave(dev);
1160 }
1157 1161
1158 return err; 1162 break;
1163 }
1164
1165 return notifier_from_errno(err);
1159} 1166}
1160 1167
1161int dsa_slave_netdevice_event(struct notifier_block *unused, 1168static int dsa_slave_port_event(struct net_device *dev, unsigned long event,
1162 unsigned long event, void *ptr) 1169 void *ptr)
1163{ 1170{
1164 struct net_device *dev;
1165 int err = 0;
1166
1167 switch (event) { 1171 switch (event) {
1168 case NETDEV_CHANGEUPPER: 1172 case NETDEV_CHANGEUPPER:
1169 dev = netdev_notifier_info_to_dev(ptr); 1173 return dsa_slave_port_upper_event(dev, event, ptr);
1170 if (!dsa_slave_dev_check(dev)) 1174 }
1171 goto out;
1172 1175
1173 err = dsa_slave_master_changed(dev); 1176 return NOTIFY_DONE;
1174 if (err && err != -EOPNOTSUPP) 1177}
1175 netdev_warn(dev, "failed to reflect master change\n");
1176 1178
1177 break; 1179int dsa_slave_netdevice_event(struct notifier_block *unused,
1178 } 1180 unsigned long event, void *ptr)
1181{
1182 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1183
1184 if (dsa_slave_dev_check(dev))
1185 return dsa_slave_port_event(dev, event, ptr);
1179 1186
1180out:
1181 return NOTIFY_DONE; 1187 return NOTIFY_DONE;
1182} 1188}