net: vertexcom: mse102x: Fix RX error handling
[ 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: 2f207cbf0d
("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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
6ac8ec92f5
commit
29ea1abc7d
@@ -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,
|
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 mse102x_net_spi *mses = to_mse102x_spi(mse);
|
||||||
struct spi_transfer *xfer = &mses->spi_xfer;
|
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",
|
netdev_err(mse->ndev, "%s: spi_sync() failed: %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
mse->stats.xfer_err++;
|
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)) {
|
} else if (*sof != cpu_to_be16(DET_SOF)) {
|
||||||
netdev_dbg(mse->ndev, "%s: SPI start of frame is invalid (0x%04x)\n",
|
netdev_dbg(mse->ndev, "%s: SPI start of frame is invalid (0x%04x)\n",
|
||||||
__func__, *sof);
|
__func__, *sof);
|
||||||
@@ -308,6 +311,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
unsigned int rxalign;
|
unsigned int rxalign;
|
||||||
unsigned int rxlen;
|
unsigned int rxlen;
|
||||||
|
bool drop = false;
|
||||||
__be16 rx = 0;
|
__be16 rx = 0;
|
||||||
u16 cmd_resp;
|
u16 cmd_resp;
|
||||||
u8 *rxpkt;
|
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",
|
net_dbg_ratelimited("%s: Unexpected response (0x%04x)\n",
|
||||||
__func__, cmd_resp);
|
__func__, cmd_resp);
|
||||||
mse->stats.invalid_rts++;
|
mse->stats.invalid_rts++;
|
||||||
return;
|
drop = true;
|
||||||
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_dbg_ratelimited("%s: Unexpected response to first CMD\n",
|
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__,
|
net_dbg_ratelimited("%s: Invalid frame length: %d\n", __func__,
|
||||||
rxlen);
|
rxlen);
|
||||||
mse->stats.invalid_len++;
|
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);
|
rxalign = ALIGN(rxlen + DET_SOF_LEN + DET_DFT_LEN, 4);
|
||||||
skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign);
|
skb = netdev_alloc_skb_ip_align(mse->ndev, rxalign);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
@@ -355,7 +367,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
|
|||||||
* They are copied, but ignored.
|
* They are copied, but ignored.
|
||||||
*/
|
*/
|
||||||
rxpkt = skb_put(skb, rxlen) - DET_SOF_LEN;
|
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++;
|
mse->ndev->stats.rx_errors++;
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user