linux/drivers/net/can
Marc Kleine-Budde c7eb923c3c can: mcp251xfd: mcp251xfd_regmap_crc_read(): work around broken CRC on TBC register
MCP251XFD_REG_TBC is the time base counter register. It increments
once per SYS clock tick, which is 20 or 40 MHz. Observation shows that
if the lowest byte (which is transferred first on the SPI bus) of that
register is 0x00 or 0x80 the calculated CRC doesn't always match the
transferred one.

To reproduce this problem let the driver read the TBC register in a
high frequency. This can be done by attaching only the mcp251xfd CAN
controller to a valid terminated CAN bus and send a single CAN frame.
As there are no other CAN controller on the bus, the sent CAN frame is
not ACKed and the mcp251xfd repeats it. If user space enables the bus
error reporting, each of the NACK errors is reported with a time
stamp (which is read from the TBC register) to user space.

$ ip link set can0 down
$ ip link set can0 up type can bitrate 500000 berr-reporting on
$ cansend can0 4FF#ff.01.00.00.00.00.00.00

This leads to several error messages per second:

| mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 3a 86 da, CRC=0x7753) retrying.
| mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=80 01 b4 da, CRC=0x5830) retrying.
| mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 e9 23 db, CRC=0xa723) retrying.
| mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 8a 30 db, CRC=0x4a9c) retrying.
| mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=80 f3 43 db, CRC=0x66d2) retrying.

If the highest bit in the lowest byte is flipped the transferred CRC
matches the calculated one. We assume for now the CRC calculation in
the chip works on wrong data and the transferred data is correct.

This patch implements the following workaround:

- If a CRC read error on the TBC register is detected and the lowest
  byte is 0x00 or 0x80, the highest bit of the lowest byte is flipped
  and the CRC is calculated again.
- If the CRC now matches, the _original_ data is passed to the reader.
  For now we assume transferred data was OK.

Link: https://lore.kernel.org/r/20210406110617.1865592-5-mkl@pengutronix.de
Cc: Manivannan Sadhasivam <mani@kernel.org>
Cc: Thomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
2021-04-07 09:31:28 +02:00
..
c_can can: c_can: remove unused enum BOSCH_C_CAN_PLATFORM 2021-04-07 09:31:28 +02:00
cc770 can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
dev can: skb: alloc_can{,fd}_skb(): set "cf" to NULL if skb allocation fails 2021-04-07 09:31:19 +02:00
ifi_canfd can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
m_can can: m_can: m_can_receive_skb(): add missing error handling to can_rx_offload_queue_sorted() call 2021-04-07 09:31:28 +02:00
mscan can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
peak_canfd module: remove never implemented MODULE_SUPPORTED_DEVICE 2021-03-17 13:16:18 -07:00
rcar can: dev: can_free_echo_skb(): extend to return can frame length 2021-03-30 11:14:28 +02:00
sja1000 can: dev: can_free_echo_skb(): extend to return can frame length 2021-03-30 11:14:28 +02:00
softing can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
spi can: mcp251xfd: mcp251xfd_regmap_crc_read(): work around broken CRC on TBC register 2021-04-07 09:31:28 +02:00
usb can: peak_usb: add support of ONE_SHOT mode 2021-03-30 11:14:47 +02:00
at91_can.c can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
flexcan.c can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate 2021-03-16 08:41:26 +01:00
grcan.c can: dev: can_free_echo_skb(): extend to return can frame length 2021-03-30 11:14:28 +02:00
janz-ican3.c can: replace can_dlc as variable/element for payload length 2020-11-20 12:04:12 +01:00
Kconfig can: grcan: add missing Kconfig dependency to HAS_IOMEM 2021-03-30 11:14:45 +02:00
kvaser_pciefd.c can: kvaser_pciefd: Always disable bus load reporting 2021-03-16 08:41:26 +01:00
led.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500 2019-06-19 17:09:55 +02:00
Makefile can: dev: move driver related infrastructure into separate subdir 2021-01-13 09:42:58 +01:00
pch_can.c can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
slcan.c net: introduce CAN specific pointer in the struct net_device 2021-02-24 14:32:15 -08:00
sun4i_can.c can: dev: can_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
ti_hecc.c can: dev: can_rx_offload_get_echo_skb(): extend to return can frame length 2021-01-14 08:43:43 +01:00
vcan.c net: introduce CAN specific pointer in the struct net_device 2021-02-24 14:32:15 -08:00
vxcan.c net: introduce CAN specific pointer in the struct net_device 2021-02-24 14:32:15 -08:00
xilinx_can.c can: xilinx_can: Simplify code by using dev_err_probe() 2021-03-30 11:14:46 +02:00