]> git.baikalelectronics.ru Git - kernel.git/commit
net: xilinx_emaclite: fix freezes due to unordered I/O
authorAnssi Hannula <anssi.hannula@bitwise.fi>
Tue, 14 Feb 2017 17:11:45 +0000 (19:11 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Feb 2017 17:18:34 +0000 (12:18 -0500)
commit63d5cc03cb6bb659b7df32191932288b2581e3e4
tree770fb7eed381111e461a0fb6d09f8b5b545b472c
parentfd59dc3ae8f0fccc6cf620ab29932a0210951ee2
net: xilinx_emaclite: fix freezes due to unordered I/O

The xilinx_emaclite uses __raw_writel and __raw_readl for register
accesses. Those functions do not imply any kind of memory barriers and
they may be reordered.

The driver does not seem to take that into account, though, and the
driver does not satisfy the ordering requirements of the hardware.
For clear examples, see xemaclite_mdio_write() and xemaclite_mdio_read()
which try to set MDIO address before initiating the transaction.

I'm seeing system freezes with the driver with GCC 5.4 and current
Linux kernels on Zynq-7000 SoC immediately when trying to use the
interface.

In commit 7d32abe130d1 ("net: emaclite: Do not use microblaze and ppc
IO functions") the driver was switched from non-generic
in_be32/out_be32 (memory barriers, big endian) to
__raw_readl/__raw_writel (no memory barriers, native endian), so
apparently the device follows system endianness and the driver was
originally written with the assumption of memory barriers.

Rather than try to hunt for each case of missing barrier, just switch
the driver to use iowrite32/ioread32/iowrite32be/ioread32be depending
on endianness instead.

Tested on little-endian Zynq-7000 ARM SoC FPGA.

Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
Fixes: 7d32abe130d1 ("net: emaclite: Do not use microblaze and ppc IO
functions")
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/xilinx/xilinx_emaclite.c