|
@@ -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;
|