diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2014-04-22 13:31:51 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2014-04-22 13:31:51 +0200 |
commit | 0ee9e84781aa368c96544e6e96a4696a5a7ba00a (patch) | |
tree | 6c02e2123d8a9b0ffdcb9c6bf6792d6737a95885 | |
parent | 98eb9572b7dc548d0013baac9240f25a644ab277 (diff) |
can: mcp251x: fix locking in BERR counter functionality
Symptoms:
The interface stops receiving CAN frames when reception of CAN frame
and call to the introduced get_berr_counter function coincide.
Reproduction:
Ip requests, among others, the berr field for the can interfaces. NOTE
that it does so even if called as 'ip link show lo', as interface-based
filtering is only done after the system calls to receive interface
information.
Run candump on a MCP-based can interface that has a lot of traffic (via
'cangen -g1' on another can node).
On the system with the MCP chip, run
while /bin/true; do ip link > /dev/null ; done;
Reception of CAN-frames (as shown by candump) will cease within
seconds.
This issue got introduced by commit
1b59090a47101b4bf379d2c35986ad3f0bcb2aa1 as access to the SPI registers
of the MCP251x were not locked.
Issue report and patch courtesy David R. Piegdon of Indurad GmbH.
-rw-r--r-- | drivers/net/can/mcp251x.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 535e4032da2b..899b152ee8ae 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -593,15 +593,22 @@ static int mcp251x_do_set_bittiming(struct net_device *net) return 0; } -static int mcp251x_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) +static int mcp251x_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) { struct mcp251x_priv *priv = netdev_priv(dev); struct spi_device *spi = priv->spi; uint8_t tec,rec; + mutex_lock(&priv->mcp_lock); + mcp251x_read_2regs(spi, TEC, &tec, &rec); + + mutex_unlock(&priv->mcp_lock); + bec->txerr = tec; bec->rxerr = rec; + return 0; } |