Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc9c89b1 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 96a94cc5 5b8d5429
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -119,6 +119,15 @@ static int br_dev_init(struct net_device *dev)
	return err;
}

static void br_dev_uninit(struct net_device *dev)
{
	struct net_bridge *br = netdev_priv(dev);

	br_multicast_uninit_stats(br);
	br_vlan_flush(br);
	free_percpu(br->stats);
}

static int br_dev_open(struct net_device *dev)
{
	struct net_bridge *br = netdev_priv(dev);
@@ -332,6 +341,7 @@ static const struct net_device_ops br_netdev_ops = {
	.ndo_open		 = br_dev_open,
	.ndo_stop		 = br_dev_stop,
	.ndo_init		 = br_dev_init,
	.ndo_uninit		 = br_dev_uninit,
	.ndo_start_xmit		 = br_dev_xmit,
	.ndo_get_stats64	 = br_get_stats64,
	.ndo_set_mac_address	 = br_set_mac_address,
@@ -356,14 +366,6 @@ static const struct net_device_ops br_netdev_ops = {
	.ndo_features_check	 = passthru_features_check,
};

static void br_dev_free(struct net_device *dev)
{
	struct net_bridge *br = netdev_priv(dev);

	free_percpu(br->stats);
	free_netdev(dev);
}

static struct device_type br_type = {
	.name	= "bridge",
};
@@ -376,7 +378,7 @@ void br_dev_setup(struct net_device *dev)
	ether_setup(dev);

	dev->netdev_ops = &br_netdev_ops;
	dev->destructor = br_dev_free;
	dev->destructor = free_netdev;
	dev->ethtool_ops = &br_ethtool_ops;
	SET_NETDEV_DEVTYPE(dev, &br_type);
	dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
+0 −1
Original line number Diff line number Diff line
@@ -311,7 +311,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)

	br_fdb_delete_by_port(br, NULL, 0, 1);

	br_vlan_flush(br);
	br_multicast_dev_del(br);
	cancel_delayed_work_sync(&br->gc_work);

+5 −2
Original line number Diff line number Diff line
@@ -2031,8 +2031,6 @@ void br_multicast_dev_del(struct net_bridge *br)

out:
	spin_unlock_bh(&br->multicast_lock);

	free_percpu(br->mcast_stats);
}

int br_multicast_set_router(struct net_bridge *br, unsigned long val)
@@ -2531,6 +2529,11 @@ int br_multicast_init_stats(struct net_bridge *br)
	return 0;
}

void br_multicast_uninit_stats(struct net_bridge *br)
{
	free_percpu(br->mcast_stats);
}

static void mcast_stats_add_dir(u64 *dst, u64 *src)
{
	dst[BR_MCAST_DIR_RX] += src[BR_MCAST_DIR_RX];
+5 −2
Original line number Diff line number Diff line
@@ -1165,11 +1165,14 @@ static int br_dev_newlink(struct net *src_net, struct net_device *dev,
		spin_unlock_bh(&br->lock);
	}

	err = br_changelink(dev, tb, data);
	err = register_netdevice(dev);
	if (err)
		return err;

	return register_netdevice(dev);
	err = br_changelink(dev, tb, data);
	if (err)
		unregister_netdevice(dev);
	return err;
}

static size_t br_get_size(const struct net_device *brdev)
+5 −0
Original line number Diff line number Diff line
@@ -620,6 +620,7 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
			const struct sk_buff *skb, u8 type, u8 dir);
int br_multicast_init_stats(struct net_bridge *br);
void br_multicast_uninit_stats(struct net_bridge *br);
void br_multicast_get_stats(const struct net_bridge *br,
			    const struct net_bridge_port *p,
			    struct br_mcast_stats *dest);
@@ -760,6 +761,10 @@ static inline int br_multicast_init_stats(struct net_bridge *br)
	return 0;
}

static inline void br_multicast_uninit_stats(struct net_bridge *br)
{
}

static inline int br_multicast_igmp_type(const struct sk_buff *skb)
{
	return 0;