If CAN bus damaged, buffers will stall in the CAN driver. In this case j1939 stack tried to resend the buffers forever. So, limit amount of retries to 10 for now. Signed-off-by: Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx> --- net/can/j1939/j1939-priv.h | 2 ++ net/can/j1939/transport.c | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/net/can/j1939/j1939-priv.h b/net/can/j1939/j1939-priv.h index 21bee33fdbf4..9ebb2c74f4f6 100644 --- a/net/can/j1939/j1939-priv.h +++ b/net/can/j1939/j1939-priv.h @@ -239,6 +239,8 @@ struct j1939_session { unsigned int total_message_size; /* Total message size, number of bytes */ unsigned int total_queued_size; /* Total number of bytes queue from socket to the session */ + unsigned int tx_retry; + int err; u32 tskey; enum j1939_session_state state; diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index 7decc38a4d46..06b77de6aa85 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -8,6 +8,8 @@ #include "j1939-priv.h" +#define J1939_XTP_TX_RETRY_LIMIT 100 + #define J1939_ETP_PGN_CTL 0xc800 #define J1939_ETP_PGN_DAT 0xc700 #define J1939_TP_PGN_CTL 0xec00 @@ -872,6 +874,7 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) { struct j1939_session *session = container_of(hrtimer, struct j1939_session, txtimer); + struct j1939_priv *priv = session->priv; int ret = 0; if (session->skcb.addr.type == J1939_SIMPLE) { @@ -889,9 +892,24 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) } if (ret == -ENOBUFS) { - j1939_tp_schedule_txtimer(session, 10 + prandom_u32_max(16)); + /* Retry limit is currently arbitrary chosen */ + if (session->tx_retry < J1939_XTP_TX_RETRY_LIMIT) { + session->tx_retry++; + j1939_tp_schedule_txtimer(session, + 10 + prandom_u32_max(16)); + } else { + netdev_alert(priv->ndev, "%s: tx retry count reached\n", + __func__); + session->err = -ENETUNREACH; + j1939_session_rxtimer_cancel(session); + j1939_session_deactivate_activate_next(session); + } } else if (ret) { + netdev_alert(priv->ndev, "%s: tx aborted with unknown reason: %i\n", + __func__, ret); j1939_session_cancel(session, J1939_XTP_ABORT_OTHER); + } else { + session->tx_retry = 0; } j1939_session_put(session); -- 2.20.1