Skip to content

Commit a526a3c

Browse files
tachicialexdavem330
authored andcommitted
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: bc93e19 ("net: ethernet: adi: Add ADIN1110 support") Signed-off-by: Alexandru Tachici <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ac3208f commit a526a3c

File tree

1 file changed

+16
-21
lines changed

1 file changed

+16
-21
lines changed

drivers/net/ethernet/adi/adin1110.c

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static int adin1110_read_reg(struct adin1110_priv *priv, u16 reg, u32 *val)
196196
{
197197
u32 header_len = ADIN1110_RD_HEADER_LEN;
198198
u32 read_len = ADIN1110_REG_LEN;
199-
struct spi_transfer t[2] = {0};
199+
struct spi_transfer t = {0};
200200
int ret;
201201

202202
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)
209209
header_len++;
210210
}
211211

212-
t[0].tx_buf = &priv->data[0];
213-
t[0].len = header_len;
214-
215212
if (priv->append_crc)
216213
read_len++;
217214

218215
memset(&priv->data[header_len], 0, read_len);
219-
t[1].rx_buf = &priv->data[header_len];
220-
t[1].len = read_len;
216+
t.tx_buf = &priv->data[0];
217+
t.rx_buf = &priv->data[0];
218+
t.len = read_len + header_len;
221219

222-
ret = spi_sync_transfer(priv->spidev, t, 2);
220+
ret = spi_sync_transfer(priv->spidev, &t, 1);
223221
if (ret)
224222
return ret;
225223

@@ -296,7 +294,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
296294
{
297295
struct adin1110_priv *priv = port_priv->priv;
298296
u32 header_len = ADIN1110_RD_HEADER_LEN;
299-
struct spi_transfer t[2] = {0};
297+
struct spi_transfer t;
300298
u32 frame_size_no_fcs;
301299
struct sk_buff *rxb;
302300
u32 frame_size;
@@ -327,12 +325,7 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
327325
return ret;
328326

329327
frame_size_no_fcs = frame_size - ADIN1110_FRAME_HEADER_LEN - ADIN1110_FEC_LEN;
330-
331-
rxb = netdev_alloc_skb(port_priv->netdev, round_len);
332-
if (!rxb)
333-
return -ENOMEM;
334-
335-
memset(priv->data, 0, round_len + ADIN1110_RD_HEADER_LEN);
328+
memset(priv->data, 0, ADIN1110_RD_HEADER_LEN);
336329

337330
priv->data[0] = ADIN1110_CD | FIELD_GET(GENMASK(12, 8), reg);
338331
priv->data[1] = FIELD_GET(GENMASK(7, 0), reg);
@@ -342,21 +335,23 @@ static int adin1110_read_fifo(struct adin1110_port_priv *port_priv)
342335
header_len++;
343336
}
344337

345-
skb_put(rxb, frame_size_no_fcs + ADIN1110_FRAME_HEADER_LEN);
338+
rxb = netdev_alloc_skb(port_priv->netdev, round_len + header_len);
339+
if (!rxb)
340+
return -ENOMEM;
346341

347-
t[0].tx_buf = &priv->data[0];
348-
t[0].len = header_len;
342+
skb_put(rxb, frame_size_no_fcs + header_len + ADIN1110_FRAME_HEADER_LEN);
349343

350-
t[1].rx_buf = &rxb->data[0];
351-
t[1].len = round_len;
344+
t.tx_buf = &priv->data[0];
345+
t.rx_buf = &rxb->data[0];
346+
t.len = header_len + round_len;
352347

353-
ret = spi_sync_transfer(priv->spidev, t, 2);
348+
ret = spi_sync_transfer(priv->spidev, &t, 1);
354349
if (ret) {
355350
kfree_skb(rxb);
356351
return ret;
357352
}
358353

359-
skb_pull(rxb, ADIN1110_FRAME_HEADER_LEN);
354+
skb_pull(rxb, header_len + ADIN1110_FRAME_HEADER_LEN);
360355
rxb->protocol = eth_type_trans(rxb, port_priv->netdev);
361356

362357
if ((port_priv->flags & IFF_ALLMULTI && rxb->pkt_type == PACKET_MULTICAST) ||

0 commit comments

Comments
 (0)