Commit 71a50419 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-fixes-for-5.9-20200815' of...

Merge tag 'linux-can-fixes-for-5.9-20200815' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2020-08-15

this is a pull request of 4 patches for net/master.

All patches are by Zhang Changzhong and fix broadcast related problems in the
j1939 CAN networking stack.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 55eff0eb 0ae18a82
......@@ -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);
......@@ -1074,9 +1076,9 @@ static void __j1939_session_cancel(struct j1939_session *session,
lockdep_assert_held(&session->priv->active_session_list_lock);
session->err = j1939_xtp_abort_to_errno(priv, err);
session->state = J1939_SESSION_WAITING_ABORT;
/* do not send aborts on incoming broadcasts */
if (!j1939_cb_is_broadcast(&session->skcb)) {
session->state = J1939_SESSION_WAITING_ABORT;
j1939_xtp_tx_abort(priv, &session->skcb,
!session->transmission,
err, session->skcb.addr.pgn);
......@@ -1673,8 +1675,12 @@ static void j1939_xtp_rx_rts(struct j1939_priv *priv, struct sk_buff *skb,
return;
}
session = j1939_xtp_rx_rts_session_new(priv, skb);
if (!session)
if (!session) {
if (cmd == J1939_TP_CMD_BAM && j1939_sk_recv_match(priv, skcb))
netdev_info(priv->ndev, "%s: failed to create TP BAM session\n",
__func__);
return;
}
} else {
if (j1939_xtp_rx_rts_session_active(session, skb)) {
j1939_session_put(session);
......@@ -1683,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);
......@@ -1738,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;
......@@ -1813,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)
......@@ -1820,7 +1833,11 @@ 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)
......@@ -1865,6 +1882,13 @@ static void j1939_xtp_rx_dat(struct j1939_priv *priv, struct sk_buff *skb)
else
j1939_xtp_rx_dat_one(session, skb);
}
if (j1939_cb_is_broadcast(skcb)) {
session = j1939_session_get_by_addr(priv, &skcb->addr, false,
false);
if (session)
j1939_xtp_rx_dat_one(session, skb);
}
}
/* j1939 main intf */
......@@ -1956,7 +1980,7 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb)
if (j1939_tp_im_transmitter(skcb))
j1939_xtp_rx_rts(priv, skb, true);
if (j1939_tp_im_receiver(skcb))
if (j1939_tp_im_receiver(skcb) || j1939_cb_is_broadcast(skcb))
j1939_xtp_rx_rts(priv, skb, false);
break;
......@@ -2020,7 +2044,7 @@ int j1939_tp_recv(struct j1939_priv *priv, struct sk_buff *skb)
{
struct j1939_sk_buff_cb *skcb = j1939_skb_to_cb(skb);
if (!j1939_tp_im_involved_anydir(skcb))
if (!j1939_tp_im_involved_anydir(skcb) && !j1939_cb_is_broadcast(skcb))
return 0;
switch (skcb->addr.pgn) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment