|
@@ -1339,7 +1339,17 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
|
|
|
|
|
|
static int ppp_dev_init(struct net_device *dev)
|
|
|
{
|
|
|
+ struct ppp *ppp;
|
|
|
+
|
|
|
netdev_lockdep_set_classes(dev);
|
|
|
+
|
|
|
+ ppp = netdev_priv(dev);
|
|
|
+ /* Let the netdevice take a reference on the ppp file. This ensures
|
|
|
+ * that ppp_destroy_interface() won't run before the device gets
|
|
|
+ * unregistered.
|
|
|
+ */
|
|
|
+ atomic_inc(&ppp->file.refcnt);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1362,6 +1372,15 @@ static void ppp_dev_uninit(struct net_device *dev)
|
|
|
wake_up_interruptible(&ppp->file.rwait);
|
|
|
}
|
|
|
|
|
|
+static void ppp_dev_priv_destructor(struct net_device *dev)
|
|
|
+{
|
|
|
+ struct ppp *ppp;
|
|
|
+
|
|
|
+ ppp = netdev_priv(dev);
|
|
|
+ if (atomic_dec_and_test(&ppp->file.refcnt))
|
|
|
+ ppp_destroy_interface(ppp);
|
|
|
+}
|
|
|
+
|
|
|
static const struct net_device_ops ppp_netdev_ops = {
|
|
|
.ndo_init = ppp_dev_init,
|
|
|
.ndo_uninit = ppp_dev_uninit,
|
|
@@ -1387,6 +1406,7 @@ static void ppp_setup(struct net_device *dev)
|
|
|
dev->tx_queue_len = 3;
|
|
|
dev->type = ARPHRD_PPP;
|
|
|
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
|
|
|
+ dev->priv_destructor = ppp_dev_priv_destructor;
|
|
|
netif_keep_dst(dev);
|
|
|
}
|
|
|
|