diff options
author | Vivien Didelot <vivien.didelot@savoirfairelinux.com> | 2016-03-13 16:21:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-14 16:05:32 -0400 |
commit | 6debb68a2d1acd1f5eca1d9d1c79a54dc998b6d6 (patch) | |
tree | d5cd4d18aca824a81c59800c3b29edbca623a488 /net/dsa/slave.c | |
parent | 16bfa7024eba5e36aff38ba62086b9027373007d (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.c | 54 |
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 | ||
457 | static void dsa_slave_bridge_port_leave(struct net_device *dev) | 457 | static 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 | ||
1146 | static int dsa_slave_master_changed(struct net_device *dev) | 1146 | static 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 | ||
1161 | int dsa_slave_netdevice_event(struct notifier_block *unused, | 1168 | static 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; | 1179 | int 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 | ||
1180 | out: | ||
1181 | return NOTIFY_DONE; | 1187 | return NOTIFY_DONE; |
1182 | } | 1188 | } |