Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> --- net/can/j1939/j1939-priv.h | 2 +- net/can/j1939/main.c | 2 +- net/can/j1939/socket.c | 2 ++ net/can/j1939/transport.c | 20 ++++++++++++++++---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/net/can/j1939/j1939-priv.h b/net/can/j1939/j1939-priv.h index d04f8c2d3658..416419890a37 100644 --- a/net/can/j1939/j1939-priv.h +++ b/net/can/j1939/j1939-priv.h @@ -208,7 +208,7 @@ void j1939_priv_get(struct j1939_priv *priv); /* notify/alert all j1939 sockets bound to ifindex */ void j1939_sk_netdev_event(struct net_device *ndev, int error_code); -int j1939_tp_rmdev_notifier(struct j1939_priv *priv); +int j1939_cancel_all_active_sessions(struct j1939_priv *priv); void j1939_tp_init(struct j1939_priv *priv); /* decrement pending skb for a j1939 socket */ diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c index 67b0b16fc4ad..ac0c22d9b4b2 100644 --- a/net/can/j1939/main.c +++ b/net/can/j1939/main.c @@ -353,12 +353,12 @@ static int j1939_netdev_notify(struct notifier_block *nb, switch (msg) { case NETDEV_UNREGISTER: - j1939_tp_rmdev_notifier(priv); j1939_sk_netdev_event(ndev, ENODEV); break; case NETDEV_DOWN: j1939_sk_netdev_event(ndev, ENETDOWN); + j1939_cancel_all_active_sessions(priv); j1939_ecu_unmap_all(priv); break; } diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c index da93afee1d0a..e599286f4c28 100644 --- a/net/can/j1939/socket.c +++ b/net/can/j1939/socket.c @@ -1110,6 +1110,8 @@ void j1939_sk_netdev_event(struct net_device *ndev, int error_code) if (!sock_flag(&jsk->sk, SOCK_DEAD)) jsk->sk.sk_error_report(&jsk->sk); + j1939_sk_queue_drop_all(jsk); + if (error_code == ENODEV) { j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa); diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index eebbe898d127..0373d64dffbf 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -1007,11 +1007,12 @@ static int j1939_simple_txnext(struct j1939_session *session) return 0; } -bool j1939_session_deactivate(struct j1939_session *session) +bool j1939_session_deactivate_locked(struct j1939_session *session) { bool active = false; - j1939_session_list_lock(session->priv); + lockdep_assert_held(&session->priv->active_session_list_lock); + if (session->state >= J1939_SESSION_ACTIVE && session->state < J1939_SESSION_ACTIVE_MAX) { active = true; @@ -1020,6 +1021,16 @@ bool j1939_session_deactivate(struct j1939_session *session) session->state = J1939_SESSION_DONE; j1939_session_put(session); } + + return active; +} + +bool j1939_session_deactivate(struct j1939_session *session) +{ + bool active; + + j1939_session_list_lock(session->priv); + active = j1939_session_deactivate_locked(session); j1939_session_list_unlock(session->priv); return active; @@ -1972,7 +1983,7 @@ void j1939_simple_recv(struct j1939_priv *priv, struct sk_buff *skb) j1939_session_put(session); } -int j1939_tp_rmdev_notifier(struct j1939_priv *priv) +int j1939_cancel_all_active_sessions(struct j1939_priv *priv) { struct j1939_session *session, *saved; @@ -1981,7 +1992,8 @@ int j1939_tp_rmdev_notifier(struct j1939_priv *priv) &priv->active_session_list, active_session_list_entry) { j1939_session_timers_cancel(session); - j1939_session_deactivate_activate_next(session); + session->err = ESHUTDOWN; + j1939_session_deactivate_locked(session); } j1939_session_list_unlock(priv); return NOTIFY_DONE; -- 2.20.1