can: j1939: add rxtimer for multipacket broadcast session
authorZhang Changzhong <zhangchangzhong@huawei.com>
Wed, 5 Aug 2020 03:50:25 +0000 (11:50 +0800)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Sat, 15 Aug 2020 09:12:58 +0000 (11:12 +0200)
According to SAE J1939/21 (Chapter 5.12.3 and APPENDIX C), for transmit side
the required time interval between packets of a multipacket broadcast message
is 50 to 200 ms, the responder shall use a timeout of 250ms (provides margin
allowing for the maximumm spacing of 200ms). For receive side a timeout will
occur when a time of greater than 750 ms elapsed between two message packets
when more packets were expected.

So this patch fix and add rxtimer for multipacket broadcast session.

Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
Signed-off-by: Zhang Changzhong <zhangchangzhong@huawei.com>
Link: https://lore.kernel.org/r/1596599425-5534-5-git-send-email-zhangchangzhong@huawei.com
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
net/can/j1939/transport.c

index 047118d..a8dd956 100644 (file)
@@ -723,10 +723,12 @@ static int j1939_session_tx_rts(struct j1939_session *session)
                return ret;
 
        session->last_txcmd = dat[0];
-       if (dat[0] == J1939_TP_CMD_BAM)
+       if (dat[0] == J1939_TP_CMD_BAM) {
                j1939_tp_schedule_txtimer(session, 50);
-
-       j1939_tp_set_rxtimeout(session, 1250);
+               j1939_tp_set_rxtimeout(session, 250);
+       } else {
+               j1939_tp_set_rxtimeout(session, 1250);
+       }
 
        netdev_dbg(session->priv->ndev, "%s: 0x%p\n", __func__, session);
 
@@ -1687,11 +1689,15 @@ static void j1939_xtp_rx_rts(struct j1939_priv *priv, struct sk_buff *skb,
        }
        session->last_cmd = cmd;
 
-       j1939_tp_set_rxtimeout(session, 1250);
-
-       if (cmd != J1939_TP_CMD_BAM && !session->transmission) {
-               j1939_session_txtimer_cancel(session);
-               j1939_tp_schedule_txtimer(session, 0);
+       if (cmd == J1939_TP_CMD_BAM) {
+               if (!session->transmission)
+                       j1939_tp_set_rxtimeout(session, 750);
+       } else {
+               if (!session->transmission) {
+                       j1939_session_txtimer_cancel(session);
+                       j1939_tp_schedule_txtimer(session, 0);
+               }
+               j1939_tp_set_rxtimeout(session, 1250);
        }
 
        j1939_session_put(session);
@@ -1742,6 +1748,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
        int offset;
        int nbytes;
        bool final = false;
+       bool remain = false;
        bool do_cts_eoma = false;
        int packet;
 
@@ -1817,6 +1824,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
            j1939_cb_is_broadcast(&session->skcb)) {
                if (session->pkt.rx >= session->pkt.total)
                        final = true;
+               else
+                       remain = true;
        } else {
                /* never final, an EOMA must follow */
                if (session->pkt.rx >= session->pkt.last)
@@ -1826,6 +1835,9 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
        if (final) {
                j1939_session_timers_cancel(session);
                j1939_session_completed(session);
+       } else if (remain) {
+               if (!session->transmission)
+                       j1939_tp_set_rxtimeout(session, 750);
        } else if (do_cts_eoma) {
                j1939_tp_set_rxtimeout(session, 1250);
                if (!session->transmission)