mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
net: ethernet: adi: adin1110: Fix SPI transfers
No need to use more than one SPI transfer for reads.
Use only one from now as ADIN1110/2111 does not tolerate
CS changes during reads.
The BCM2711/2708 SPI controllers worked fine, but the NXP
IMX8MM could not keep CS lowered during SPI bursts.
This change aims to make the ADIN1110/2111 driver compatible
with both SPI controllers, without any loss of bandwidth/other
capabilities.
Fixes: bc93e19d08
("net: ethernet: adi: Add ADIN1110 support")
Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ac3208fbac
commit
a526a3cc9c
@ -196,7 +196,7 @@ static int adin1110_read_reg(struct adin1110_priv *priv, u16 reg, u32 *val)
|
||||
{
|
||||
u32 header_len = ADIN1110_RD_HEADER_LEN;
|
||||
u32 read_len = ADIN1110_REG_LEN;
|
||||
struct spi_transfer t[2] = {0};
|
||||
struct spi_transfer t = {0};
|
||||
int ret;
|
||||
|
||||
priv->data[0] = ADIN1110_CD | FIELD_GET(GENMASK(12, 8), reg);
|
||||
@ -209,17 +209,15 @@ static int adin1110_read_reg(struct adin1110_priv *priv, u16 reg, u32 *val)
|
||||
header_len++;
|
||||
}
|
||||
|
||||
t[0].tx_buf = &priv->data[0];
|
||||
t[0].len = header_len;
|
||||
|
||||
if (priv->append_crc)
|
||||
read_len++;
|
||||
|
||||
memset(&priv->data[header_len], 0, read_len);
|
||||
t[1].rx_buf = &priv->data[header_len];
|
||||
t[1].len = read_len;
|
||||
t.tx_buf = &priv->data[0];
|
||||
t.rx_buf = &priv->data[0];
|
||||
t.len = read_len + header_len;
|
||||
|
||||
ret = spi_sync_transfer(priv->spidev, t, 2);
|
||||
ret = spi_sync_transfer(priv->spidev, &t, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -296,7 +294,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
|
||||
{
|
||||
struct adin1110_priv *priv = port_priv->priv;
|
||||
u32 header_len = ADIN1110_RD_HEADER_LEN;
|
||||
struct spi_transfer t[2] = {0};
|
||||
struct spi_transfer t;
|
||||
u32 frame_size_no_fcs;
|
||||
struct sk_buff *rxb;
|
||||
u32 frame_size;
|
||||
@ -327,12 +325,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
|
||||
return ret;
|
||||
|
||||
frame_size_no_fcs = frame_size - ADIN1110_FRAME_HEADER_LEN - ADIN1110_FEC_LEN;
|
||||
|
||||
rxb = netdev_alloc_skb(port_priv->netdev, round_len);
|
||||
if (!rxb)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(priv->data, 0, round_len + ADIN1110_RD_HEADER_LEN);
|
||||
memset(priv->data, 0, ADIN1110_RD_HEADER_LEN);
|
||||
|
||||
priv->data[0] = ADIN1110_CD | FIELD_GET(GENMASK(12, 8), reg);
|
||||
priv->data[1] = FIELD_GET(GENMASK(7, 0), reg);
|
||||
@ -342,21 +335,23 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
|
||||
header_len++;
|
||||
}
|
||||
|
||||
skb_put(rxb, frame_size_no_fcs + ADIN1110_FRAME_HEADER_LEN);
|
||||
rxb = netdev_alloc_skb(port_priv->netdev, round_len + header_len);
|
||||
if (!rxb)
|
||||
return -ENOMEM;
|
||||
|
||||
t[0].tx_buf = &priv->data[0];
|
||||
t[0].len = header_len;
|
||||
skb_put(rxb, frame_size_no_fcs + header_len + ADIN1110_FRAME_HEADER_LEN);
|
||||
|
||||
t[1].rx_buf = &rxb->data[0];
|
||||
t[1].len = round_len;
|
||||
t.tx_buf = &priv->data[0];
|
||||
t.rx_buf = &rxb->data[0];
|
||||
t.len = header_len + round_len;
|
||||
|
||||
ret = spi_sync_transfer(priv->spidev, t, 2);
|
||||
ret = spi_sync_transfer(priv->spidev, &t, 1);
|
||||
if (ret) {
|
||||
kfree_skb(rxb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
skb_pull(rxb, ADIN1110_FRAME_HEADER_LEN);
|
||||
skb_pull(rxb, header_len + ADIN1110_FRAME_HEADER_LEN);
|
||||
rxb->protocol = eth_type_trans(rxb, port_priv->netdev);
|
||||
|
||||
if ((port_priv->flags & IFF_ALLMULTI && rxb->pkt_type == PACKET_MULTICAST) ||
|
||||
|
Loading…
Reference in New Issue
Block a user