--- a/net/can/j1939/j1939-priv.h +++ b/net/can/j1939/j1939-priv.h @@ -59,6 +59,7 @@ struct j1939_priv { /* segments need a lock to protect the above list */ rwlock_t lock; + int unregistered; struct net_device *ndev; /* list of 256 ecu ptrs, that cache the claimed addresses. --- a/net/can/j1939/main.c +++ b/net/can/j1939/main.c @@ -157,13 +157,15 @@ static void __j1939_priv_release(struct struct j1939_priv *priv = container_of(kref, struct j1939_priv, kref); struct net_device *ndev = priv->ndev; - netdev_dbg(priv->ndev, "%s: 0x%p\n", __func__, priv); + if (!priv->unregistered) + netdev_dbg(priv->ndev, "%s: 0x%p\n", __func__, priv); WARN_ON_ONCE(!list_empty(&priv->active_session_list)); WARN_ON_ONCE(!list_empty(&priv->ecus)); WARN_ON_ONCE(!list_empty(&priv->j1939_socks)); - dev_put(ndev); + if (!priv->unregistered) + dev_put(ndev); kfree(priv); } @@ -377,6 +379,10 @@ static int j1939_netdev_notify(struct no j1939_sk_netdev_event_netdown(priv); j1939_ecu_unmap_all(priv); break; + case NETDEV_UNREGISTER: + priv->unregistered++; + dev_put(priv->ndev); + break; } j1939_priv_put(priv);