Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52c793f2 authored by Wolfgang Grandegger's avatar Wolfgang Grandegger Committed by David S. Miller
Browse files

can: netlink support for bus-error reporting and counters



This patch makes the bus-error reporting configurable and allows to
retrieve the CAN TX and RX bus error counters via netlink interface.
I have added support for the SJA1000. The TX and RX bus error counters
are also copied to the data fields 6..7 of error messages when state
changes are reported.

Signed-off-by: default avatarWolfgang Grandegger <wg@grandegger.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 78ca90ea
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -574,6 +574,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
	[IFLA_CAN_BITTIMING_CONST]
				= { .len = sizeof(struct can_bittiming_const) },
	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) },
};

static int can_changelink(struct net_device *dev,
@@ -649,6 +650,8 @@ static size_t can_get_size(const struct net_device *dev)
	size += nla_total_size(sizeof(u32));  /* IFLA_CAN_RESTART_MS */
	size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */
	size += sizeof(struct can_clock);     /* IFLA_CAN_CLOCK */
	if (priv->do_get_berr_counter)        /* IFLA_CAN_BERR_COUNTER */
		size += sizeof(struct can_berr_counter);
	if (priv->bittiming_const)	      /* IFLA_CAN_BITTIMING_CONST */
		size += sizeof(struct can_bittiming_const);

@@ -659,6 +662,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
{
	struct can_priv *priv = netdev_priv(dev);
	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
	struct can_berr_counter bec;
	enum can_state state = priv->state;

	if (priv->do_get_state)
@@ -669,6 +673,8 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
	NLA_PUT(skb, IFLA_CAN_BITTIMING,
		sizeof(priv->bittiming), &priv->bittiming);
	NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock);
	if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec))
		NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec);
	if (priv->bittiming_const)
		NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST,
			sizeof(*priv->bittiming_const), priv->bittiming_const);
+22 −3
Original line number Diff line number Diff line
@@ -130,8 +130,12 @@ static void set_normal_mode(struct net_device *dev)
		/* check reset bit */
		if ((status & MOD_RM) == 0) {
			priv->can.state = CAN_STATE_ERROR_ACTIVE;
			/* enable all interrupts */
			/* enable interrupts */
			if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
				priv->write_reg(priv, REG_IER, IRQ_ALL);
			else
				priv->write_reg(priv, REG_IER,
						IRQ_ALL & ~IRQ_BEI);
			return;
		}

@@ -203,6 +207,17 @@ static int sja1000_set_bittiming(struct net_device *dev)
	return 0;
}

static int sja1000_get_berr_counter(const struct net_device *dev,
				    struct can_berr_counter *bec)
{
	struct sja1000_priv *priv = netdev_priv(dev);

	bec->txerr = priv->read_reg(priv, REG_TXERR);
	bec->rxerr = priv->read_reg(priv, REG_RXERR);

	return 0;
}

/*
 * initialize SJA1000 chip:
 *   - reset chip
@@ -437,6 +452,8 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
				CAN_ERR_CRTL_TX_PASSIVE :
				CAN_ERR_CRTL_RX_PASSIVE;
		}
		cf->data[6] = txerr;
		cf->data[7] = rxerr;
	}

	priv->can.state = state;
@@ -567,7 +584,9 @@ struct net_device *alloc_sja1000dev(int sizeof_priv)
	priv->can.bittiming_const = &sja1000_bittiming_const;
	priv->can.do_set_bittiming = sja1000_set_bittiming;
	priv->can.do_set_mode = sja1000_set_mode;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
	priv->can.do_get_berr_counter = sja1000_get_berr_counter;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
		CAN_CTRLMODE_BERR_REPORTING;

	if (sizeof_priv)
		priv->priv = (void *)priv + sizeof(struct sja1000_priv);
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ struct can_priv {
	int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
	int (*do_get_state)(const struct net_device *dev,
			    enum can_state *state);
	int (*do_get_berr_counter)(const struct net_device *dev,
				   struct can_berr_counter *bec);

	unsigned int echo_skb_max;
	struct sk_buff **echo_skb;
+14 −4
Original line number Diff line number Diff line
@@ -69,6 +69,14 @@ enum can_state {
	CAN_STATE_MAX
};

/*
 * CAN bus error counters
 */
struct can_berr_counter {
	__u16 txerr;
	__u16 rxerr;
};

/*
 * CAN controller mode
 */
@@ -77,10 +85,11 @@ struct can_ctrlmode {
	__u32 flags;
};

#define CAN_CTRLMODE_LOOPBACK	0x1	/* Loopback mode */
#define CAN_CTRLMODE_LISTENONLY	0x2 	/* Listen-only mode */
#define CAN_CTRLMODE_3_SAMPLES	0x4	/* Triple sampling mode */
#define CAN_CTRLMODE_ONE_SHOT	0x8	/* One-Shot mode */
#define CAN_CTRLMODE_LOOPBACK		0x01	/* Loopback mode */
#define CAN_CTRLMODE_LISTENONLY		0x02 	/* Listen-only mode */
#define CAN_CTRLMODE_3_SAMPLES		0x04	/* Triple sampling mode */
#define CAN_CTRLMODE_ONE_SHOT		0x08	/* One-Shot mode */
#define CAN_CTRLMODE_BERR_REPORTING	0x10	/* Bus-error reporting */

/*
 * CAN device statistics
@@ -106,6 +115,7 @@ enum {
	IFLA_CAN_CTRLMODE,
	IFLA_CAN_RESTART_MS,
	IFLA_CAN_RESTART,
	IFLA_CAN_BERR_COUNTER,
	__IFLA_CAN_MAX
};