From cf124db566e6b036b8bcbe8decbed740bdfac8c6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 May 2017 12:52:56 -0400 Subject: net: Fix inconsistent teardown and release of private netdev state. Network devices can allocate reasources and private memory using netdev_ops->ndo_init(). However, the release of these resources can occur in one of two different places. Either netdev_ops->ndo_uninit() or netdev->destructor(). The decision of which operation frees the resources depends upon whether it is necessary for all netdev refs to be released before it is safe to perform the freeing. netdev_ops->ndo_uninit() presumably can occur right after the NETDEV_UNREGISTER notifier completes and the unicast and multicast address lists are flushed. netdev->destructor(), on the other hand, does not run until the netdev references all go away. Further complicating the situation is that netdev->destructor() almost universally does also a free_netdev(). This creates a problem for the logic in register_netdevice(). Because all callers of register_netdevice() manage the freeing of the netdev, and invoke free_netdev(dev) if register_netdevice() fails. If netdev_ops->ndo_init() succeeds, but something else fails inside of register_netdevice(), it does call ndo_ops->ndo_uninit(). But it is not able to invoke netdev->destructor(). This is because netdev->destructor() will do a free_netdev() and then the caller of register_netdevice() will do the same. However, this means that the resources that would normally be released by netdev->destructor() will not be. Over the years drivers have added local hacks to deal with this, by invoking their destructor parts by hand when register_netdevice() fails. Many drivers do not try to deal with this, and instead we have leaks. Let's close this hole by formalizing the distinction between what private things need to be freed up by netdev->destructor() and whether the driver needs unregister_netdevice() to perform the free_netdev(). netdev->priv_destructor() performs all actions to free up the private resources that used to be freed by netdev->destructor(), except for free_netdev(). netdev->needs_free_netdev is a boolean that indicates whether free_netdev() should be done at the end of unregister_netdevice(). Now, register_netdevice() can sanely release all resources after ndo_ops->ndo_init() succeeds, by invoking both ndo_ops->ndo_uninit() and netdev->priv_destructor(). And at the end of unregister_netdevice(), we invoke netdev->priv_destructor() and optionally call free_netdev(). Signed-off-by: David S. Miller --- drivers/net/can/vxcan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/can/vxcan.c') diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 7fbb24795681..30cf2368becf 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -156,7 +156,7 @@ static void vxcan_setup(struct net_device *dev) dev->tx_queue_len = 0; dev->flags = (IFF_NOARP|IFF_ECHO); dev->netdev_ops = &vxcan_netdev_ops; - dev->destructor = free_netdev; + dev->needs_free_netdev = true; } /* forward declaration for rtnl_create_link() */ -- cgit v1.2.3 From 97edec3a11cf6f73f2e45c3035b5ff8e4c3543dd Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 2 Jun 2017 19:37:30 +0200 Subject: can: enable CAN FD for virtual CAN devices by default CAN FD capable CAN interfaces can handle (classic) CAN 2.0 frames too. New users usually fail at their first attempt to explore CAN FD on virtual CAN interfaces due to the current CAN_MTU default. Set the MTU to CANFD_MTU by default to reduce this confusion. If someone *really* needs a 'classic CAN'-only device this can be set with the 'ip' tool with e.g. 'ip link set vcan0 mtu 16' as before. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vcan.c | 2 +- drivers/net/can/vxcan.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/can/vxcan.c') diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0eda1b308583..a8cb33264ff1 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -152,7 +152,7 @@ static const struct net_device_ops vcan_netdev_ops = { static void vcan_setup(struct net_device *dev) { dev->type = ARPHRD_CAN; - dev->mtu = CAN_MTU; + dev->mtu = CANFD_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 30cf2368becf..cfe889e8f172 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -150,7 +150,7 @@ static const struct net_device_ops vxcan_netdev_ops = { static void vxcan_setup(struct net_device *dev) { dev->type = ARPHRD_CAN; - dev->mtu = CAN_MTU; + dev->mtu = CANFD_MTU; dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; -- cgit v1.2.3