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

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
Loading
Loading
Loading
Loading
+36 −12
Original line number Diff line number Diff line
@@ -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, 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,12 +1689,16 @@ 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) {
	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) {