Commit 9c0532f9 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'linux-can-next-for-5.15-20210804' of...

Merge tag 'linux-can-next-for-5.15-20210804' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next



Marc Kleine-Budde says:

====================
pull-request: can-next 2021-08-04

this is a pull request of 5 patches for net-next/master.

The first patch is by me and fixes a typo in a comment in the CAN
J1939 protocol.

The next 2 patches are by Oleksij Rempel and update the CAN J1939
protocol to send RX status updates via the error queue mechanism.

The next patch is by me and adds a missing variable initialization to
the flexcan driver (the problem was introduced in the current net-next
cycle).

The last patch is by Aswath Govindraju and adds power-domains to the
Bosch m_can DT binding documentation.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 51b8f812 d85165b2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -104,6 +104,12 @@ properties:
          maximum: 32
    maxItems: 1

  power-domains:
    description:
      Power domain provider node and an args specifier containing
      the can device id value.
    maxItems: 1

  can-transceiver:
    $ref: can-transceiver.yaml#

+1 −1
Original line number Diff line number Diff line
@@ -649,7 +649,7 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)

static int flexcan_clks_enable(const struct flexcan_priv *priv)
{
	int err;
	int err = 0;

	if (priv->clk_ipg) {
		err = clk_prepare_enable(priv->clk_ipg);
+9 −0
Original line number Diff line number Diff line
@@ -78,11 +78,20 @@ enum {
enum {
	J1939_NLA_PAD,
	J1939_NLA_BYTES_ACKED,
	J1939_NLA_TOTAL_SIZE,
	J1939_NLA_PGN,
	J1939_NLA_SRC_NAME,
	J1939_NLA_DEST_NAME,
	J1939_NLA_SRC_ADDR,
	J1939_NLA_DEST_ADDR,
};

enum {
	J1939_EE_INFO_NONE,
	J1939_EE_INFO_TX_ABORT,
	J1939_EE_INFO_RX_RTS,
	J1939_EE_INFO_RX_DPO,
	J1939_EE_INFO_RX_ABORT,
};

struct j1939_filter {
+7 −3
Original line number Diff line number Diff line
@@ -20,9 +20,12 @@

struct j1939_session;
enum j1939_sk_errqueue_type {
	J1939_ERRQUEUE_ACK,
	J1939_ERRQUEUE_SCHED,
	J1939_ERRQUEUE_ABORT,
	J1939_ERRQUEUE_TX_ACK,
	J1939_ERRQUEUE_TX_SCHED,
	J1939_ERRQUEUE_TX_ABORT,
	J1939_ERRQUEUE_RX_RTS,
	J1939_ERRQUEUE_RX_DPO,
	J1939_ERRQUEUE_RX_ABORT,
};

/* j1939 devices */
@@ -87,6 +90,7 @@ struct j1939_priv {
	struct list_head j1939_socks;

	struct kref rx_kref;
	u32 rx_tskey;
};

void j1939_ecu_put(struct j1939_ecu *ecu);
+108 −33
Original line number Diff line number Diff line
@@ -905,20 +905,33 @@ static struct sk_buff *j1939_sk_alloc_skb(struct net_device *ndev,
	return NULL;
}

static size_t j1939_sk_opt_stats_get_size(void)
static size_t j1939_sk_opt_stats_get_size(enum j1939_sk_errqueue_type type)
{
	switch (type) {
	case J1939_ERRQUEUE_RX_RTS:
		return
			nla_total_size(sizeof(u32)) + /* J1939_NLA_TOTAL_SIZE */
			nla_total_size(sizeof(u32)) + /* J1939_NLA_PGN */
			nla_total_size(sizeof(u64)) + /* J1939_NLA_SRC_NAME */
			nla_total_size(sizeof(u64)) + /* J1939_NLA_DEST_NAME */
			nla_total_size(sizeof(u8)) +  /* J1939_NLA_SRC_ADDR */
			nla_total_size(sizeof(u8)) +  /* J1939_NLA_DEST_ADDR */
			0;
	default:
		return
			nla_total_size(sizeof(u32)) + /* J1939_NLA_BYTES_ACKED */
			0;
	}
}

static struct sk_buff *
j1939_sk_get_timestamping_opt_stats(struct j1939_session *session)
j1939_sk_get_timestamping_opt_stats(struct j1939_session *session,
				    enum j1939_sk_errqueue_type type)
{
	struct sk_buff *stats;
	u32 size;

	stats = alloc_skb(j1939_sk_opt_stats_get_size(), GFP_ATOMIC);
	stats = alloc_skb(j1939_sk_opt_stats_get_size(type), GFP_ATOMIC);
	if (!stats)
		return NULL;

@@ -928,32 +941,67 @@ j1939_sk_get_timestamping_opt_stats(struct j1939_session *session)
		size = min(session->pkt.tx_acked * 7,
			   session->total_message_size);

	switch (type) {
	case J1939_ERRQUEUE_RX_RTS:
		nla_put_u32(stats, J1939_NLA_TOTAL_SIZE,
			    session->total_message_size);
		nla_put_u32(stats, J1939_NLA_PGN,
			    session->skcb.addr.pgn);
		nla_put_u64_64bit(stats, J1939_NLA_SRC_NAME,
				  session->skcb.addr.src_name, J1939_NLA_PAD);
		nla_put_u64_64bit(stats, J1939_NLA_DEST_NAME,
				  session->skcb.addr.dst_name, J1939_NLA_PAD);
		nla_put_u8(stats, J1939_NLA_SRC_ADDR,
			   session->skcb.addr.sa);
		nla_put_u8(stats, J1939_NLA_DEST_ADDR,
			   session->skcb.addr.da);
		break;
	default:
		nla_put_u32(stats, J1939_NLA_BYTES_ACKED, size);
	}

	return stats;
}

void j1939_sk_errqueue(struct j1939_session *session,
static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
				enum j1939_sk_errqueue_type type)
{
	struct j1939_priv *priv = session->priv;
	struct sock *sk = session->sk;
	struct j1939_sock *jsk;
	struct sock_exterr_skb *serr;
	struct sk_buff *skb;
	char *state = "UNK";
	int err;

	/* currently we have no sk for the RX session */
	if (!sk)
		return;

	jsk = j1939_sk(sk);

	if (!(jsk->state & J1939_SOCK_ERRQUEUE))
		return;

	skb = j1939_sk_get_timestamping_opt_stats(session);
	switch (type) {
	case J1939_ERRQUEUE_TX_ACK:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK))
			return;
		break;
	case J1939_ERRQUEUE_TX_SCHED:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED))
			return;
		break;
	case J1939_ERRQUEUE_TX_ABORT:
		break;
	case J1939_ERRQUEUE_RX_RTS:
		fallthrough;
	case J1939_ERRQUEUE_RX_DPO:
		fallthrough;
	case J1939_ERRQUEUE_RX_ABORT:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE))
			return;
		break;
	default:
		netdev_err(priv->ndev, "Unknown errqueue type %i\n", type);
	}

	skb = j1939_sk_get_timestamping_opt_stats(session, type);
	if (!skb)
		return;

@@ -964,36 +1012,42 @@ void j1939_sk_errqueue(struct j1939_session *session,
	serr = SKB_EXT_ERR(skb);
	memset(serr, 0, sizeof(*serr));
	switch (type) {
	case J1939_ERRQUEUE_ACK:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)) {
			kfree_skb(skb);
			return;
		}

	case J1939_ERRQUEUE_TX_ACK:
		serr->ee.ee_errno = ENOMSG;
		serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
		serr->ee.ee_info = SCM_TSTAMP_ACK;
		state = "ACK";
		state = "TX ACK";
		break;
	case J1939_ERRQUEUE_SCHED:
		if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)) {
			kfree_skb(skb);
			return;
		}

	case J1939_ERRQUEUE_TX_SCHED:
		serr->ee.ee_errno = ENOMSG;
		serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
		serr->ee.ee_info = SCM_TSTAMP_SCHED;
		state = "SCH";
		state = "TX SCH";
		break;
	case J1939_ERRQUEUE_ABORT:
	case J1939_ERRQUEUE_TX_ABORT:
		serr->ee.ee_errno = session->err;
		serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
		serr->ee.ee_info = J1939_EE_INFO_TX_ABORT;
		state = "ABT";
		state = "TX ABT";
		break;
	case J1939_ERRQUEUE_RX_RTS:
		serr->ee.ee_errno = ENOMSG;
		serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
		serr->ee.ee_info = J1939_EE_INFO_RX_RTS;
		state = "RX RTS";
		break;
	case J1939_ERRQUEUE_RX_DPO:
		serr->ee.ee_errno = ENOMSG;
		serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
		serr->ee.ee_info = J1939_EE_INFO_RX_DPO;
		state = "RX DPO";
		break;
	case J1939_ERRQUEUE_RX_ABORT:
		serr->ee.ee_errno = session->err;
		serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
		serr->ee.ee_info = J1939_EE_INFO_RX_ABORT;
		state = "RX ABT";
		break;
	default:
		netdev_err(priv->ndev, "Unknown errqueue type %i\n", type);
	}

	serr->opt_stats = true;
@@ -1008,6 +1062,27 @@ void j1939_sk_errqueue(struct j1939_session *session,
		kfree_skb(skb);
};

void j1939_sk_errqueue(struct j1939_session *session,
		       enum j1939_sk_errqueue_type type)
{
	struct j1939_priv *priv = session->priv;
	struct j1939_sock *jsk;

	if (session->sk) {
		/* send TX notifications to the socket of origin  */
		__j1939_sk_errqueue(session, session->sk, type);
		return;
	}

	/* spread RX notifications to all sockets subscribed to this session */
	spin_lock_bh(&priv->j1939_socks_lock);
	list_for_each_entry(jsk, &priv->j1939_socks, list) {
		if (j1939_sk_recv_match_one(jsk, &session->skcb))
			__j1939_sk_errqueue(session, &jsk->sk, type);
	}
	spin_unlock_bh(&priv->j1939_socks_lock);
};

void j1939_sk_send_loop_abort(struct sock *sk, int err)
{
	sk->sk_err = err;
Loading