aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-04-11 22:22:45 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-11 22:22:45 -0400
commitfc9c89b19c56813434c3d2967652a4fa6906926a (patch)
tree78c0c74da30e3525566ef791dc9330872dba71ba /net
parent96a94cc5158859943b7e4e72ae69e572815f5413 (diff)
parent5b8d5429daa05bebef6ffd3297df3b502cc6f184 (diff)
Merge branch 'bridge-register-netdev-before-changelink'
Ido Schimmel says: ==================== bridge: Fix kernel oops during bridge creation First patch adds a missing ndo_uninit() in the bridge driver, which is a prerequisite for the second patch that actually fixes the oops. Please consider both patches for 4.4.y, 4.9.y and 4.10.y ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_device.c20
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_multicast.c7
-rw-r--r--net/bridge/br_netlink.c7
-rw-r--r--net/bridge/br_private.h5
5 files changed, 26 insertions, 14 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ea71513fca21..90f49a194249 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -119,6 +119,15 @@ static int br_dev_init(struct net_device *dev)
119 return err; 119 return err;
120} 120}
121 121
122static void br_dev_uninit(struct net_device *dev)
123{
124 struct net_bridge *br = netdev_priv(dev);
125
126 br_multicast_uninit_stats(br);
127 br_vlan_flush(br);
128 free_percpu(br->stats);
129}
130
122static int br_dev_open(struct net_device *dev) 131static int br_dev_open(struct net_device *dev)
123{ 132{
124 struct net_bridge *br = netdev_priv(dev); 133 struct net_bridge *br = netdev_priv(dev);
@@ -332,6 +341,7 @@ static const struct net_device_ops br_netdev_ops = {
332 .ndo_open = br_dev_open, 341 .ndo_open = br_dev_open,
333 .ndo_stop = br_dev_stop, 342 .ndo_stop = br_dev_stop,
334 .ndo_init = br_dev_init, 343 .ndo_init = br_dev_init,
344 .ndo_uninit = br_dev_uninit,
335 .ndo_start_xmit = br_dev_xmit, 345 .ndo_start_xmit = br_dev_xmit,
336 .ndo_get_stats64 = br_get_stats64, 346 .ndo_get_stats64 = br_get_stats64,
337 .ndo_set_mac_address = br_set_mac_address, 347 .ndo_set_mac_address = br_set_mac_address,
@@ -356,14 +366,6 @@ static const struct net_device_ops br_netdev_ops = {
356 .ndo_features_check = passthru_features_check, 366 .ndo_features_check = passthru_features_check,
357}; 367};
358 368
359static void br_dev_free(struct net_device *dev)
360{
361 struct net_bridge *br = netdev_priv(dev);
362
363 free_percpu(br->stats);
364 free_netdev(dev);
365}
366
367static struct device_type br_type = { 369static struct device_type br_type = {
368 .name = "bridge", 370 .name = "bridge",
369}; 371};
@@ -376,7 +378,7 @@ void br_dev_setup(struct net_device *dev)
376 ether_setup(dev); 378 ether_setup(dev);
377 379
378 dev->netdev_ops = &br_netdev_ops; 380 dev->netdev_ops = &br_netdev_ops;
379 dev->destructor = br_dev_free; 381 dev->destructor = free_netdev;
380 dev->ethtool_ops = &br_ethtool_ops; 382 dev->ethtool_ops = &br_ethtool_ops;
381 SET_NETDEV_DEVTYPE(dev, &br_type); 383 SET_NETDEV_DEVTYPE(dev, &br_type);
382 dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; 384 dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 8ac1770aa222..56a2a72e7738 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -311,7 +311,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
311 311
312 br_fdb_delete_by_port(br, NULL, 0, 1); 312 br_fdb_delete_by_port(br, NULL, 0, 1);
313 313
314 br_vlan_flush(br);
315 br_multicast_dev_del(br); 314 br_multicast_dev_del(br);
316 cancel_delayed_work_sync(&br->gc_work); 315 cancel_delayed_work_sync(&br->gc_work);
317 316
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b760f2620abf..faa7261a992f 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -2031,8 +2031,6 @@ void br_multicast_dev_del(struct net_bridge *br)
2031 2031
2032out: 2032out:
2033 spin_unlock_bh(&br->multicast_lock); 2033 spin_unlock_bh(&br->multicast_lock);
2034
2035 free_percpu(br->mcast_stats);
2036} 2034}
2037 2035
2038int br_multicast_set_router(struct net_bridge *br, unsigned long val) 2036int br_multicast_set_router(struct net_bridge *br, unsigned long val)
@@ -2531,6 +2529,11 @@ int br_multicast_init_stats(struct net_bridge *br)
2531 return 0; 2529 return 0;
2532} 2530}
2533 2531
2532void br_multicast_uninit_stats(struct net_bridge *br)
2533{
2534 free_percpu(br->mcast_stats);
2535}
2536
2534static void mcast_stats_add_dir(u64 *dst, u64 *src) 2537static void mcast_stats_add_dir(u64 *dst, u64 *src)
2535{ 2538{
2536 dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX]; 2539 dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX];
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index a8f6acd23e30..225ef7d53701 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -1165,11 +1165,14 @@ static int br_dev_newlink(struct net *src_net, struct net_device *dev,
1165 spin_unlock_bh(&br->lock); 1165 spin_unlock_bh(&br->lock);
1166 } 1166 }
1167 1167
1168 err = br_changelink(dev, tb, data); 1168 err = register_netdevice(dev);
1169 if (err) 1169 if (err)
1170 return err; 1170 return err;
1171 1171
1172 return register_netdevice(dev); 1172 err = br_changelink(dev, tb, data);
1173 if (err)
1174 unregister_netdevice(dev);
1175 return err;
1173} 1176}
1174 1177
1175static size_t br_get_size(const struct net_device *brdev) 1178static size_t br_get_size(const struct net_device *brdev)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 61368186edea..0d177280aa84 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -620,6 +620,7 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
620void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, 620void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
621 const struct sk_buff *skb, u8 type, u8 dir); 621 const struct sk_buff *skb, u8 type, u8 dir);
622int br_multicast_init_stats(struct net_bridge *br); 622int br_multicast_init_stats(struct net_bridge *br);
623void br_multicast_uninit_stats(struct net_bridge *br);
623void br_multicast_get_stats(const struct net_bridge *br, 624void br_multicast_get_stats(const struct net_bridge *br,
624 const struct net_bridge_port *p, 625 const struct net_bridge_port *p,
625 struct br_mcast_stats *dest); 626 struct br_mcast_stats *dest);
@@ -760,6 +761,10 @@ static inline int br_multicast_init_stats(struct net_bridge *br)
760 return 0; 761 return 0;
761} 762}
762 763
764static inline void br_multicast_uninit_stats(struct net_bridge *br)
765{
766}
767
763static inline int br_multicast_igmp_type(const struct sk_buff *skb) 768static inline int br_multicast_igmp_type(const struct sk_buff *skb)
764{ 769{
765 return 0; 770 return 0;