| From 263c828b01ead6407c366f2e72d148aaac7d05d6 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 30 Apr 2025 15:30:43 +0200 |
| Subject: net: vertexcom: mse102x: Fix RX error handling |
| |
| From: Stefan Wahren <wahrenst@gmx.net> |
| |
| [ Upstream commit ee512922ddd7d64afe2b28830a88f19063217649 ] |
| |
| In case the CMD_RTS got corrupted by interferences, the MSE102x |
| doesn't allow a retransmission of the command. Instead the Ethernet |
| frame must be shifted out of the SPI FIFO. Since the actual length is |
| unknown, assume the maximum possible value. |
| |
| Fixes: 2f207cbf0dd4 ("net: vertexcom: Add MSE102x SPI support") |
| Signed-off-by: Stefan Wahren <wahrenst@gmx.net> |
| Reviewed-by: Andrew Lunn <andrew@lunn.ch> |
| Link: https://patch.msgid.link/20250430133043.7722-5-wahrenst@gmx.net |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/vertexcom/mse102x.c | 20 ++++++++++++++++---- |
| 1 file changed, 16 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c |
| index 2b1aac72601d0..060a566bc6aae 100644 |
| --- a/drivers/net/ethernet/vertexcom/mse102x.c |
| +++ b/drivers/net/ethernet/vertexcom/mse102x.c |
| @@ -263,7 +263,7 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp, |
| } |
| |
| static int mse102x_rx_frame_spi(struct mse102x_net *mse, u8 *buff, |
| - unsigned int frame_len) |
| + unsigned int frame_len, bool drop) |
| { |
| struct mse102x_net_spi *mses = to_mse102x_spi(mse); |
| struct spi_transfer *xfer = &mses->spi_xfer; |
| @@ -281,6 +281,9 @@ static int mse102x_rx_frame_spi(struct mse102x_net *mse, u8 *buff, |
| netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n", |
| __func__, ret); |
| mse->stats.xfer_err++; |
| + } else if (drop) { |
| + netdev_dbg(mse->ndev, "%s: Drop frame\n", __func__); |
| + ret = -EINVAL; |
| } else if (*sof != cpu_to_be16(DET_SOF)) { |
| netdev_dbg(mse->ndev, "%s: SPI start of frame is invalid (0x%04x)\n", |
| __func__, *sof); |
| @@ -308,6 +311,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) |
| struct sk_buff *skb; |
| unsigned int rxalign; |
| unsigned int rxlen; |
| + bool drop = false; |
| __be16 rx = 0; |
| u16 cmd_resp; |
| u8 *rxpkt; |
| @@ -330,7 +334,8 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) |
| net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n", |
| __func__, cmd_resp); |
| mse->stats.invalid_rts++; |
| - return; |
| + drop = true; |
| + goto drop; |
| } |
| |
| net_dbg_ratelimited("%s: Unexpected response to first CMD\n", |
| @@ -342,9 +347,16 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) |
| net_dbg_ratelimited("%s: Invalid frame length: %d\n", __func__, |
| rxlen); |
| mse->stats.invalid_len++; |
| - return; |
| + drop = true; |
| } |
| |
| + /* In case of a invalid CMD_RTS, the frame must be consumed anyway. |
| + * So assume the maximum possible frame length. |
| + */ |
| +drop: |
| + if (drop) |
| + rxlen = VLAN_ETH_FRAME_LEN; |
| + |
| rxalign = ALIGN(rxlen + DET_SOF_LEN + DET_DFT_LEN, 4); |
| skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign); |
| if (!skb) |
| @@ -355,7 +367,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse) |
| * They are copied, but ignored. |
| */ |
| rxpkt = skb_put(skb, rxlen) - DET_SOF_LEN; |
| - if (mse102x_rx_frame_spi(mse, rxpkt, rxlen)) { |
| + if (mse102x_rx_frame_spi(mse, rxpkt, rxlen, drop)) { |
| mse->ndev->stats.rx_errors++; |
| dev_kfree_skb(skb); |
| return; |
| -- |
| 2.39.5 |
| |