net: vertexcom: mse102x: Fix RX error handling
authorStefan Wahren <wahrenst@gmx.net>
Wed, 30 Apr 2025 13:30:43 +0000 (15:30 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 1 May 2025 14:24:05 +0000 (07:24 -0700)
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>
drivers/net/ethernet/vertexcom/mse102x.c

index 2c06d1d05164fc3770192cc5f5fddd54c344a642..e4d993f31374070a9b3ba7a1eed5c24ddd292776 100644 (file)
@@ -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;